DB의 설계상에서 key를 단일 키만 사용하는 경우는 거의 없습니다.
대부분 복합 key를 사용하여 DB설계를 하고 있습니다.
그래서 JPA에서 복합 키를 어떻게 표현할 수 있는지 공부해 보겠습니다.
DB에서는 FK(외래 키)가 기본 키에 포함되는지 여부에 따라 식별,비식별 관계로 구분됩니다.
보통 비식별 관계를 주로 사용하고 필요한 상황에서 식별 관계를 사용합니다.
기본 키+외래 키
로 사용합니다.복합 키를 표현할 때는 JPA에서는 식별자 클래스를 만들어야 합니다.
그리고 식별자 클래스는 @IdClass, @EmbededId
두개의 어노테이션 중 하나를 선택해서 사용하면 됩니다.
간단하게 설명하면 @IdClass 는 DB에 가까운 방법, @EmbededId는 객체지향에 가까운 방법입니다.
식별자 클래스의 equals(),hashCode()
는 속성 컨텍스트가 식별자를 비교할때 사용하기 때문에 반드시 오버라이딩 해줘야합니다!!
@Entity
@IdClass(ParentId.class)
public class Parent{
@Id
@Column(name = "parent_id1")
private Int id1;
@Id
@Column(name = "parent_id2")
private Int id2;
private String name;
@NoArgsConstructor
@AllArgsConstructor
public class ParentId implements Serializable
priavte Int id1;
private Int id2;
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
@Override
public int hashCode() {
return super.hashCode();
}
@Entity
public class child{
@Id
private Int id;
@ManyToOne
@JoinColumns({
@JoinColumn(name = "parent_id1", referencedColumnName = "parent_id1"),
@JoinColumn(name = "parent_id2", referencedColumnName = "parent_id2")
})
private Parent parent;
코드를 순서대로 살펴보겠습니다.
복합 키를 사용하기 위해서는 식별자 클래스를 만들어야 합니다.그래서 ParentId 식별자 클래스를 생성하였습니다.
Parent 에서 @IdClass(ParentId.class)를 선언하여 식별자 클래스를 지정하였습니다.
Child에서는 복합 키 매핑을 위해 @JoinColumns를 이용하고 각각의 Key는 @JoinColumn으로 매핑해줍니다.
referencedColumnName
속성이 name 속성과 동일할 때 생략이 가능하나, 미지정하였을 때는 @JoinColumns
에 선언된 @JoinColumn의 순서가 바뀌어 저장 될 수 있습니다.
referencedColumnName 속성을 지정하기를 권장 합니다.
@Entity
public class Parent{
@EmbeddedId
private ParentId id1;
private String name;
}
@Embeddable
@NoArgsConstructor
@AllArgsConstructor
public class ParentId implements Serializable {
@Column(name = "parent_id1")
private Int id1;
@Column(name = "parent_id2")
private Int id2;
@Override
public boolean equals(Object obj) {
return super.equals(obj);
}
@Override
public int hashCode() {
return super.hashCode();
}