위의 다이어그램을 @EmbeddedId를 이용하여 작성해보면 다음과 같다.
// 부모
@Entity
public class Parent {
@Id
@Column(name = "PARENT_ID")
private String id;
private String name;
}
// 자식
public class Child {
@EmbeddedId
private ChildId id;
@MapsId("parentId") // ChildId.parentId 매핑
@ManyToOne
@JoinColumn(name = "PARENT_ID")
public Parent parent;
}
// 자식 ID
@Embeddable
public class ChildId implements Serializable {
pirvate String parentId; // @MapsId("parentId")로 매핑
@Column(name = "CHILD_ID")
private String id;
// equals, hashCode
}
// 손자
public class GrandChild {
@EmbeddedId
private GrandChildId id;
@MapsId("childId") // GrandChildId.childId 매핑
@ManyToOne
@JoinColumns({
@JoinColumn(name = "PARENT_ID", referrencedColumnName = "PARENT_ID"),
@JoinColumn(name = "CHILD_ID", referrencedColumnName = "CHILD_ID")
})
private Child child;
}
// 손자 ID
public class GrandChildId implements Serializable {
private ChildId childId; // @MapsId("childId")로 매핑
@Column(name = "GRANDCHILD_ID")
private String id;
// equals, hashCode
}
식별관계에서 @IdClass와 @EmbeddedId는 그리 큰 차이를 보이지 않는 것 같다.
@IdClass와 다른 점은 @Id
대신 @MapsId
를 사용한다는 점이다.
그렇다면 @MapsId
에 대해 좀 알아보자. GrandChild
에서 아래코드에 집중해보자.
@MapsId("childId") // GrandChildId.childId 매핑
@ManyToOne
@JoinColumns({
@JoinColumn(name = "PARENT_ID", referrencedColumnName = "PARENT_ID"),
@JoinColumn(name = "CHILD_ID", referrencedColumnName = "CHILD_ID")
})
private Child child;
@MapsId
가 없었다면 위의 코드는 단순히 외래키 매핑이다.@MapsId("childId")
가 있음으로써 childId를 기본키로도 매핑 하게 되는 것아래와 같이 코드를 작성하면 저장이 잘 됨을 알 수 있다.
Parent parent = new Parent();
parent.setName("PARENT_NAME#1");
parent.setId("PARENT#1");
em.persist(parent);
ChildId childId = new ChildId();
childId.setParent(parent.getId());
childId.setId("CHILD#1");
Child child = new Child();
child.setId(childId);
child.setParent(parent);
em.persist(child);
GrandChildId grandChildId = new GrandChildId();
grandChildId.setId("GRANDCHILD#1");
grandChildId.setChildId(childId);
GrandChild grandChild = new GrandChild();
grandChild.setId(grandChildId);
grandChild.setChild(child);
em.persist(grandChild);