@IdClass
사용DB에 맞춘 방법
ParentId.class
) 생성equals
와 hashCode
를 오버라이딩하여 구현
주의점
public
이어야 한다.public class ParentId implements Serializable {
private Long id1;
private Long id2;
// 기본 생성자
public ParentId(){}
public ParentId(Long id1, Long id2){
this.id1 = id1;
this.id2 = id2;
}
@Override
public boolean equals(Object o){...}
@Override
public int hashCode(){...}
}
@IdClass(ParentId.class)
와 같이 식별자 클래스를 매핑해준다.@Entity
@IdClass(ParentId.class)
public class Parent {
@Id
private Long id1;
@Id
private Long id2;
...
}
복합 키를 사용하는 엔티티를 저장할 때, 해당 엔티티의 복합 키의 값만 지정해준다. 그러면 내부적으로 알아서, 해당 값들로 식별자 클래스(ParentId)를 생성하고, 영속성 컨텍스트의 키 값으로 사용한다.
따라서, 저장할 때는 식별자 클래스를 지정해서 저장하지 않았음에도 불구하고, 조회할 때는 식별자 클래스의 값으로 영속성 컨텍스트에서 조회해야 한다.
자식 클래스 구성
@Entity
public class Child {
@Id
private Long id;
@ManyToOne
@JoinColumns({ // 속성이랑 컬럼이랑 같으면, 후자는 생략 가능
@JoinColumn(name="parent_id1", referencedColumnName = "id1"),
@JoinColumn(name="parent_id2", referencedColumnName = "id2")
})
private Parent parent;
}
‼‼ 이건 내가 헷갈려서 ‼‼
@EmbeddedId
좀 더 객체지향에 맞춘 방법
ParentId
)는 @Embeddable
어노테이션 사용@Embeddable
public class ParentId implements Serializable {
private Long id1;
private Long id2;
@Override
public boolean equals(Object o){...}
@Override
public int hashCode(){...}
}
ParentId
)를 복합 키를 사용하는 클래스(Parent
)에 속성으로 직접 매핑한다. @EmbeddedId
어노테이션을 사용한다.@Entity
public class Parent {
@EmbeddedId
private ParentId id;
private String name;
//equals and hashCode 구현
...
}
복합 키를 사용하는 엔티티를 저장할 때, 직접 식별자 클래스(parentId
)를 생성 후, 엔티티에 속성 값을 설정 해준 다음 저장한다.
조회는 식별자 클래스를 통해서 일어난다.
equals
와 hashCode
복합 키를 구성하는 식별자 클래스에 필수적으로 구현해야 한다.
영속성 컨텍스트는 식별자를 통해서 엔티티를 관리한다. 그리고 식별자를 구분할 때는 equals
와 hashCode
를 사용한다.
하지만, Object
클래스가 제공하는 기본 equals()
는 인스턴스의 참조 값 비교인 ==
, 동일성 비교만을 제공한다.
따라서, equals
와 hashCode
를 구현하지 않는다면, 영속성 컨텍스트가 엔티티를 관리하는데 문제를 발생시킨다.
@GeneratedValue
복합 키를 사용하게 되면, @GeneratedValue
를 사용할 수 없다.
여러 개 중, 단 하나라도 적용 불가!