12. [JPA] 복합키
대부분의 엔티티에는 @Id 애노테이션을 한 개 사용한다.
하지만 테이블의 키가 복합키로 이뤄져 있다면 엔티티를 설계할 때에 이를 고려해야 한다.
복합키 설정 방법은 두 가지가 있다.
1 2 | @Embeddable 이용하는 방법 @IdClass 이용하는 방법 | cs |
첫 번째 방법이 객체지향 방식에 가깝다고 한다.
두 번째 방법은 DB 방식에 가깝다고 하는데 잘 와닿지는 않는다.
@Embeddable 이용 방법
다음과 같이 emp 테이블이 존재한다.
emp 테이블의 키는 emp_name, emp_no 두 개의 복합키로 이뤄져 있다.
1 2 3 4 5 6 | create table emp ( emp_name varchar(255) not null, emp_no integer not null, name varchar(255), primary key (emp_name, emp_no) ) | cs |
@EmbeddedId 를 이용하여 엔티티를 설계할 때에는 우선 Serializable 인터페이스를 구현한 클래스를 선언하고 필드에 복합키로 사용되는 컬럼을 선언하면 된다.
그리고 @Embeddable 애노테이션을 추가해 주자.
1 2 3 4 5 6 7 8 9 10 | @Data @Embeddable class EmpId implements Serializable { @Column(name = "EMP_NO") private int empNo; @Column(name = "EMP_NAME") private String empName; } | cs |
복합키에 대한 클래스를 생성했으니 이를 엔티티와 결합시켜야 한다.
방법은 간단하다.
Emp 엔티티 클래스 내부에 복합키를 위한 클래스인 EmpId를 객체 연관 관계로 설정하면 된다.
그리고 @EmbeddedId 애노테이션을 붙여주면 설정 끝
1 2 3 4 5 6 7 8 9 | @Data @Entity class Emp { @EmbeddedId private EmpId empId; private String phone; } | cs |
테스트를 해보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | @Test @Transactional public void testEmbeddable() { EmpId empId = new EmpId(); empId.setEmpNo(1); empId.setEmpName("nklee"); Emp emp = new Emp(); emp.setEmpId(empId); emp.setPhone("010-1111-1111"); em.persist(emp); em.flush(); em.clear(); emp = em.find(Emp.class, empId); assertThat(1, is(emp.getEmpId().getEmpNo())); assertThat("nklee", is(emp.getEmpId().getEmpName())); } | cs |
@IdClass 이용 방법
order_id, product_id 복합키를 가지는 order_product 테이블이 존재한다.
1 2 3 4 5 6 | create table order_product ( order_id integer not null, product_id integer not null, amount integer not null, primary key (order_id, product_id) ) | cs |
Serializable 인터페이스를 구현한 클래스를 선언하고 필드를 정의하자.
1 2 3 4 5 | @Data class OrderProductPK implements Serializable { private int orderId; private int productId; } | cs |
위와 같이 정의한 후 엔티티 클래스에 @IdClass(OrderProductPK.class) 설정을 추가해 주면 된다.
유의해야 할 부분은 OrderProduct 엔티티의 식별자 orderId 필드 이름이 OrderProductPK의 orderId 필드 이름과 같아야 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @Data @Entity @IdClass(OrderProductPK.class) class OrderProduct { @Id @Column(name = "ORDER_ID") private int orderId; @Id @Column(name = "PRODUCT_ID") private int productId; private int amount; } | cs |
테스트 해보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @Test @Transactional public void testIdClass() { OrderProduct orderProduct = new OrderProduct(); orderProduct.setOrderId(1); orderProduct.setProductId(2); orderProduct.setAmount(1000); em.persist(orderProduct); em.flush(); em.clear(); OrderProductPK pk = new OrderProductPK(); pk.setOrderId(1); pk.setProductId(2); orderProduct = em.find(OrderProduct.class, pk); assertThat(1, is(orderProduct.getOrderId())); assertThat(2, is(orderProduct.getProductId())); assertThat(1000, is(orderProduct.getAmount())); } | cs |
'프로그래밍' 카테고리의 다른 글
2. Spring Cloud를 이용한 MSA 구축하기 - config server (0) | 2017.09.22 |
---|---|
1. Spring Cloud를 이용한 MSA 구축하기 - spring cloud (0) | 2017.09.21 |
14. [JPA] Lock - 잠금 (0) | 2017.09.20 |
13. [JPA] 트랜잭션 격리 수준 (Transaction Isolation Level) (0) | 2017.09.12 |
11. [JPA] Querydsl (0) | 2017.09.01 |
spring data elasticsearch 사용해 보기 (6) | 2017.08.31 |
10. [JPA] JPQL (0) | 2017.08.28 |
9. [JPA] @Enumerated (0) | 2017.08.23 |