복합키란?
복합 키(Composite Key)는 두 개 이상의 PK를 하나로 PK로 지정하는 것을 말한다. 이러한 복합키를 가지고 있는 논리 모델은 식별 관계와 비식별 관계로 구분되어 사용한다.
식별 관계
부모테이블의 기본키를 상속 받고 자식 테이블의 기본키 + 외래키의 구조로 사용되는 구조 입니다.
비식별 관계
비식별 관계는 부모 테이블의 기본키만 받아서 자식 테이블의 FK로 사용하는 것이 비식별 관계입니다. 이러한 관계는 FK가 Null이냐 아니냐에 따라서 필수적 비식별 관계와 선택적 비식별 관계로 구분되어집니다. JPA는 이러한 식별, 비식별 관계를 모두 제공합니다.
JPA에서의 복합키
JPA에서는 아래와 같은 두개의 식별자를 사용하려면 오류가 발생하기 때문에 별도의 식별자 클래스를 만들어야합니다.
// 에러 발생
@Entity
public class CompositeTestEntity {
@Id
@GeneratedValue
private Long id;
@Id
@GeneratedValue
private Long id2;
}
JPA는 영속성 컨텍스트에 Entity를 보관할 때 엔티티의 식별자를 키로 사용한다. 그리고 식별자를 구분하기 위해 equals()와 hashCode()를 사용하여 동등성을 비교합니다. 식별자 필드가 하나라면 override할 필요 없이 사용해도 되지만 두개라면 재정의 하여 사용을 해야 한다. JPA에서는 복합키를 제공하기 위해 @IdClass와 @EmbeddedId를 제공하는데 @EmbeddedId가 객체지향적으로 사용하기에 좀 더 가깝다고 볼 수 있습니다.
@IdClass
아이디 클래스
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@NoArgsConstructor
@AllArgsConstructor
public class ParentId implements Serializable {
private String parentId1;
private String parentId2;
}
상속받는 클래스
@Entity
@IdClass(ParentId.class)
public class Parent {
@Id
@Column(name = "PARENT_ID_1")
private String parentId1;
@Id
@Column(name = "PARENT_ID_2")
private String parentId2;
}
@IdClass 사용할 때 주의할 점
- Serializable(직렬화 하기 위함)을 implements 받아야 한다.
- equal, hashCode method를 구현해야 한다. 기본 생성자가 존재해야 한다.
- public class 이여야 한다.
- Entity Class의 필드명과 동일한 필드를 가지고 있어야 한다.
@EmbeddedId
아이디 클래스
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@NoArgsConstructor
@AllArgsConstructor
@Embeddedable
public class ParentId implements Serializable {
@Column(name="PARENT_ID1")
private String parentId1;
@Column(name="PARENT_ID2")
private String parentId2;
}
상속받는 클래스
@Entity
public class Parent {
@EmbeddedId
private ParentId parentId;
}
@EmbeddedId
를 적용한 식별자 클래스는 다음 조건을 만족해야합니다.
@Embeddedable
어노테이션을 붙여야합니다.- Serializable 인터페이스를 구현하여야 합니다.
- equal, hashCode method를 구현해야 한다.
- 기본 생성자가 존재해야 한다.
- 식별자 클래스는 퍼블릭이여야 합니다.
✔︎ Equals와 HashCode를 구현하는 이유
영속성 컨텍스트에서 Entity를 구분하는데 id를 사용하는데 해당 동등성 비교는 equals를 통해 이루어집니다. 자바에서 Object 동등성 비교는 ==을 통해 이루어져서 적절하게 구현하지 않았다면 영속성 컨텍스트를 통해 엔티티를 관리하는데 큰 문제가 발생할 수 있기 때문 입니다.
'JAVA > JPA' 카테고리의 다른 글
<JPA> 네이티브 SQL 사용 (0) | 2022.10.22 |
---|---|
<JPA> Criteria의 사용 방법 (0) | 2022.10.22 |
JPA 상속관계 (0) | 2022.09.24 |
@OneToOne 관계에서 지연로딩(LAZY)이 안되는 문제 (0) | 2022.09.18 |
(JPA) fetch join (0) | 2021.08.12 |