[JPA] JavaEE 환경(Spring)에서 JPA 설정 및 CRUD

2020. 9. 7. 12:46 Java 관련/JPA

프로젝트 구조

  • DB는 편의상 H2 DB 사용
  • 구현체는 Hibernate 사용
  • Spring 자체 설정보다는 JPA 설정 예제를 위해 Spring Boot 사용
  • Maven 기반 프로젝트
  • JPA란 무엇인가? 에 나오는 user, order 테이블을 예제로 사용 

 

 

JPAConfig.java

  • LocalContainerEntityManagerFactoryBean : EntityManagerFactoryBean을 Spring에서 사용하기 위한 클래스
  • JpaVendorAdapter : JPA는 여러 구현체가 존재하기 때문에 구현체별 설정을 지원하기 위한 클래스이다. 나는 hibernate를 사용하기 때문에 HibernateJpaVendorAdapter를 사용한다.
@Configuration
@EnableTransactionManagement
public class JPAConfig {
 
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource());
        em.setPackagesToScan("net.woniper.jpa.domain");
 
        // persistence 설정
        Properties properties = new Properties();
        properties.setProperty("hibernate.hbm2ddl.auto", "create-drop");
        properties.setProperty("hibernate.show_sql", "true");
 
        // 각 구현체의 프로퍼티 확장 및 설정
        JpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(jpaVendorAdapter);
        em.setJpaProperties(properties);
        return em;
    }
 
    // H2 DB 설정
    @Bean(destroyMethod = "shutdown")
    public EmbeddedDatabase dataSource() {
        return new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.H2)
                .setName("slipp")
                .build();
    }
 
    // Transaction 설정
    @Bean
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(emf);
        return transactionManager;
    }
}

Entity(Domain)

  • JPA에서 Entity는 하나의 테이블 객체를 표현한 것이라고 생각해 된다.
  • @Entity가 테이블 정보이며 변수가 필드가 되는 것이다.

 

@Entity(name = "tbl_user")
public class User {
 
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer userId;
    private String username;
    private String nickName;
    private String address;
 
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    private List<Order> orders;
 
    public Integer getUserId() {
        return userId;
    }
 
    public void setUserId(Integer userId) {
        this.userId = userId;
    }
 
    public String getUsername() {
        return username;
    }
 
    public void setUsername(String username) {
        this.username = username;
    }
 
    public String getNickName() {
        return nickName;
    }
 
    public void setNickName(String nickName) {
        this.nickName = nickName;
    }
 
    public String getAddress() {
        return address;
    }
 
    public void setAddress(String address) {
        this.address = address;
    }
 
    public List<Order> getOrders() {
        return orders;
    }
 
    public void setOrders(List<Order> orders) {
        this.orders = orders;
    }
 
    public int totalPrice() {
        int totalPrice = 0;
        for (Order order : orders) {
            totalPrice += order.getPrice();
        }
        return totalPrice;
    }
 
    @Override
    public String toString() {
        return "User{" +
                "userId=" + userId +
                ", username='" + username + '\'' +
                ", nickName='" + nickName + '\'' +
                ", address='" + address + '\'' +
                ", orders=" + orders +
                '}';
    }
}
 
 
@Entity(name = "tbl_order")
public class Order {
 
    @Id @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer orderId;
    private String orderName;
    private String note;
    private int price;
 
    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "user_id")
    private User user;
 
    public Order(String orderName, String note, int price, User user) {
        this.orderName = orderName;
        this.note = note;
        this.price = price;
        this.user = user;
    }
 
    public Integer getOrderId() {
        return orderId;
    }
 
    public void setOrderId(Integer orderId) {
        this.orderId = orderId;
    }
 
    public String getOrderName() {
        return orderName;
    }
 
    public void setOrderName(String orderName) {
        this.orderName = orderName;
    }
 
    public String getNote() {
        return note;
    }
 
    public void setNote(String note) {
        this.note = note;
    }
 
    public User getUser() {
        return user;
    }
 
    public void setUser(User user) {
        this.user = user;
    }
 
    public int getPrice() {
        return price;
    }
 
    public void setPrice(int price) {
        this.price = price;
    }
 
    @Override
    public String toString() {
        return "Order{" +
                "orderId=" + orderId +
                ", orderName='" + orderName + '\'' +
                ", note='" + note +
                '}' + "\n";
    }
}

JPACRUDTest.java

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SpringBootJpaApplication.class)
@WebAppConfiguration
public class JPACRUDTest {
 
    @PersistenceUnit
    private EntityManagerFactory persistenceEntityManager;
 
    @Autowired
    private EntityManagerFactory entityManagerFactory;
    private EntityManager entityManager;
    private User user;
 
    @Test
    public void configTest() {
        assertNotNull(persistenceEntityManager);
        assertNotNull(entityManagerFactory);
    }
 
    @Test
    public void update() {
        // update
        User updateUser = entityManager.find(User.class, user.getUserId());
        updateUser.setNickName("update nickName");
        updateUser.setAddress("update address");
 
        entityManager.merge(updateUser);
 
        // persistence Context Test
        assertEquals("update nickName", user.getNickName());
        assertEquals("update address", user.getAddress());
 
        // update Tests
        assertEquals("update nickName", updateUser.getNickName());
        assertEquals("update address", updateUser.getAddress());
    }
 
    @Test
    public void delete() {
        User getUser = entityManager.find(User.class, user.getUserId());
        entityManager.remove(getUser);
        User deleteUser = entityManager.find(User.class, user.getUserId());
        assertNull(deleteUser);
    }
 
    @Test
    public void select() {
        User findUser = entityManager.find(User.class, user.getUserId());
        assertEquals(user.getUserId(), findUser.getUserId());
        assertEquals(user.getUsername(), findUser.getUsername());
        assertEquals(user.getNickName(), findUser.getNickName());
        assertEquals(user.getAddress(), findUser.getAddress());
        assertEquals(user.totalPrice(), 145);
 
        // order
        assertEquals(user.getOrders().size(), 10);
    }
 
    @Before
    public void setUp() throws Exception {
        entityManager = entityManagerFactory.createEntityManager();
        entityManager.getTransaction().begin();
 
        // fixture
        user = new User();
        user.setUsername("kyungwon");
        user.setNickName("woniper");
        user.setAddress("seoul");
        List<Order> orders = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Order order = new Order("order" + i, "note" + i, i + 10,  user);
            entityManager.persist(order);
            orders.add(order);
        }
        user.setOrders(orders);
        entityManager.persist(user);
        System.out.println("============ fixture ===========\n" + user);
    }
 
    @After
    public void after() {
        entityManager.getTransaction().commit();
        entityManager.close();
    }
 
}

 

출처 : https://blog.woniper.net/258?category=531455