woniper

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

Framework

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

woniper1 2015. 5. 2. 19:51
  1. JPA란 무엇인가?
  2. JavaSE 환경에서 JPA 설정 및 CRUD
  3. JavaEE 환경(Spring)에서 JPA 설정 및 CRUD
  4. @OneToOne, 1:1 관계 매핑
  5. @OneToMany / @ManyToOne, 1:N / N:1 관계 매핑
  6. @ManyToMany, N:M 관계 매핑
  7. Entity 객체 생명주기(Lifecycle)와 Persistence Context


프로젝트 구조

  • 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();
	}

}


Comments