- 참조: 자바 ORM 표준 JPA 프로그래밍
- M : N 연결 엔티티, 비식별
앞에서 M : N 연결 엔티티를 알아보았다. 복합 키를 사용하기 위해 @IdClass 를 추가하고, 식별자 클래스를 지정하였다. 식별자 클래스는 Serializable 을 구현해야하고, equals 와 hashCode 재정의 및 그 외에도 지켜야하는 규약이 있었다. USER_PRODUCT 테이블에서 복합키를 사용했었는데 DB 설계를 해본사람이라면 이를 그대로 사용하지는 않을 것이다.
위의 다이어그램에서 USER_PRODUCT 테이블의 명이 ORDERS 로 변경되었다. 회원이 상품을 몇개 그리고 언제 주문했는지 정보를 추가하면서 비즈니스에서 주문이라는 업무의 성격이 되었기 때문이다. 또 ORDER_ID 를 추가하여 PK 로 지정하였다. 이제 USER_ID 와 PRODUCT_ID 는 외래키(FK)의 역할만 하고 복합 키의 역할은 하지 않는다.
어차피 ORDER_ID 를 추가하지 않아도 USER_ID 와 PRODUCT_ID 를 복합 키로 참조하면 1 개의 엔티티라는걸 인식할 수 있는데 왜 굳이 ORDER_ID 라는 신규 컬럼을 추가하여 PK 로 지정했을까?
우선 까다로운 식별자 클래스를 추가생성하지 않아도 되고, 영속화시키는 코드도 더 깔끔해진다. 만약 다른 엔티티에서 ORDERS 를 참조하여 ORDERS 에 대한 외래키를 관리한다고 해도 ORDER_ID 만 JoinColumn 으로 지정해주면 된다.
@Entity
public class Orders {
@Id @GeneratedValue
@Column(name = "ORDER_ID")
private Long id;
@ManyToOne
@JoinColumn(name = "USER_ID")
private User user;
@ManyToOne
@JoinColumn(name = "PRODUCT_ID")
private Product product;
private int orderAmount;
@Temporal(TemporalType.TIMESTAMP)
private Date orderDate;
User 와 Product 의 변동사항은 없다. UserProduct 는 주문의 역할을 하므로 이름도 Orders 로 변경해준다. ORDER_ID pk 를 추가해주고 식별자 클래스를 지정하였던 @IdClass 를 삭제한다.
public static void save(EntityManager em) {
EntityTransaction tx = em.getTransaction();
tx.begin();
Product product = new Product();
product.setId("PRODUCT#1");
product.setName("Product Name#1");
em.persist(product);
User user = new User();
user.setId("USER#1");
user.setUserName("User Name#1");
em.persist(user);
Orders order = new Orders();
order.setUser(user);
order.setProduct(product);
order.setOrderAmount(2);
order.setOrderDate(new Date());
em.persist(order);
tx.commit();
em.close();
}
public static void find(EntityManager em) {
EntityTransaction tx = em.getTransaction();
tx.begin();
Orders userProduct = em.find(Orders.class, (long) 1);
System.out.println("UserProduct Info=============");
System.out.println(userProduct);
tx.commit();
em.close();
}
save 와 find 도 위와 같이 변경해준다. 특히 find 는 ORDER_ID pk 하나로 검색할 수 있게 되어 훨씬 간단하교 명료해졌다.
H2 Console 에서도 위와 같이 추가된 ORDER_ID 컬럼이 반영되었다.
- 식별과 비식별
결국 M : N 은 1 : M 과 N : 1 로 변환하여 맵핑해야 한다. 그리고 중간 엔티티를 둘 때 앞의 글과 지금글에서 살펴보았던 식별과 비식별 관계 둘 중 하나를 택해서 JPA 코드를 작성한다.
식별관계는 식별자(PRODUCT_ID, USER_ID) 를 기본키와 외래키로 사용한다. 반면 비식별관계는 기본키를 별도로 생성하고, 식별자를 외래키로만 사용한다.
보통의 경우엔 비식별관계를 많이 사용한다. 앞에서도 언급했듯이 JPA 코드측면에서 식별자클래스 규약을 신경쓰지 않아도 되고, 해당 테이블 참조시 2 개의 키를 모두 관리하지 않아도 되기 때문이다.
'Framework and Tool > JPA' 카테고리의 다른 글
JPA - 고급맵핑 - 슈퍼타입과 서브타입 (0) | 2021.07.10 |
---|---|
JPA - 다양한 연관관계 - 요구사항 분석과 맵핑 2 (0) | 2021.07.10 |
JPA - 다양한 연관관계 - M : N 식별관계 (0) | 2021.07.10 |
JPA - 다양한 연관관계 - M : N (0) | 2021.07.08 |
JPA - 다양한 연관관계 - 1 : 1 (0) | 2021.07.06 |
댓글