카테고리 없음
JPA 고급매핑 (3)
머룽
2023. 4. 20. 09:52
복합키 식별 관계 매핑
부모, 자식, 손자까지 계속 기본 키를 전달하는 식별관계가 있다고 치자 식별 관계에서 자식 테이블은 부모 테이블의 기본 키를 포함해서 복합 키를 구성해야 하므로 @IdClass 나 @EmbeddedId를 사용해서 식별자를 매핑해야 한다. (일대일 관계랑은 약간 다르다.)@IdClass
@Entity
@Data
public class Parent {
@Id
@Column(name = "PARENT_ID")
private String id;
private String name;
}
@Entity
@Data
@IdClass(ChildId.class)
public class Child {
@Id
@ManyToOne
@JoinColumn(name = "PARENT_ID")
private Parent parent;
@Id
@Column(name = "CHILD_ID")
private String childId;
private String name;
}
@Data
public class ChildId implements Serializable {
private String parent;
private String childId;
}
@Entity
@Data
@IdClass(GrandChildId.class)
public class CrandChild {
@Id
@ManyToOne
@JoinColumns({
@JoinColumn(name = "PARENT_ID"),
@JoinColumn(name = "CHILD_ID"),
})
private Child child;
@Id
@Column(name = "GRANDCHILD_ID")
private String id;
private String name;
}
@Data
public class GrandChildId implements Serializable{
private ChildId child;
private String id;
}
식별 관계는 기본 키와 외래 키를 같이 매핑 해야 한다. 따라서 식별자 매핑인 @Id와 연관관계 매핑인 @ManyToOne을 같이 사용하면 된다.
@Id
@ManyToOne
@JoinColumn(name = "PARENT_ID")
private Parent parent;
Child 엔티티의 Parent 필드를 보면 @Id로 기본 키를 매핑하면서 @ManyToOne과 @JoinColumn으로 외래 키를 같이 매핑한다.
EmbeddedId와 식별 관계
@Entity
@Data
public class Parent {
@Id
@Column(name = "PARENT_ID")
private String id;
private String name;
}
@Entity
@Data
public class Child {
@EmbeddedId
private ChildId id;
@MapsId("parentId") //ChildId.parentId 매핑
@ManyToOne
@JoinColumn(name = "PARENT_ID")
private Parent parent;
private String name;
}
@Data
@Embeddable
public class ChildId implements Serializable {
private String parentId; //@MapsId("parentId") 로 매핑
private String childId;
}
@Entity
@Data
public class CrandChild {
@EmbeddedId
private GrandChildId id;
@MapsId("childId") // GrandChildId.childId 매핑
@ManyToOne
@JoinColumns({
@JoinColumn(name = "PARENT_ID"),
@JoinColumn(name = "CHILD_ID"),
})
private Child child;
private String name;
}
@Data
@Embeddable
public class GrandChildId implements Serializable{
private ChildId childId; //@MapsId("childId") 로 매핑
@Column(name = "GRANDCHILD_ID")
private String id;
}
@EmbeddedId는 식별 관계로 사용할 연관관계의 속성에 @MapsId를 사용하면 된다. Child 엔티티 parent 필드를 보자
@MapsId("parentId") //ChildId.parentId 매핑
@ManyToOne
@JoinColumn(name = "PARENT_ID")
private Parent parent;
@IdClass와 다른 점은 @Id 대신에 @MapsId를 사용한 점이다. @MapsId는 외래 키와 매핑한 연관관계를 기본 키에도 매핑하겠다는 뜻이다. @MapsId의 속성 값은 @EmbeddedId를 사용한 식별자 클래스의 기본 키 필드를 지정하면 된다. 여기서는 ChildId의 parentId 필드를 선택했다.
비식별 관계로 구현
@Data
@Entity
public class Parent {
@Id
@GeneratedValue
@Column(name = "PARENT_ID")
private Long id;
private String name;
}
@Entity
@Data
public class Child {
@Id
@GeneratedValue
@Column(name = "CHILD_ID")
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "PARENT_ID")
private Parent parent;
}
@Data
@Entity
public class GrandChild {
@Id
@GeneratedValue
@Column(name = "GRANDCHILD_ID")
private Long id;
private String name;
@ManyToOne
@JoinColumn(name = "CHILD_ID")
private Child child;
}
식별 관계의 복합 키를 사용한 코드와 비교하면 매핑도 쉽고 코드도 단순하다. 그리고 복합 키가 없으므로 복합 키 클래스를 만들지 않아도 된다.
일대일 식별 관계
일대일 식별관계는 자식 테이블의 기본 키 값으로 부모테이블의 기본 키 값만 사용한다. 그래서 부모 테이블의 기본 키가 복합 키가 아니면 자식 테이블의 기본 키는 복합 키로 구성하지 않아도 된다.@Entity
@Data
public class Board {
@Id
@GeneratedValue
@Column(name = "BOARD_ID")
private Long id;
private String title;
@OneToOne(mappedBy = "board")
private BoardDetail boardDetail;
}
@Entity
@Data
public class BoardDetail {
@Id
private Long boardId;
@MapsId
@OneToOne
@JoinColumn(name = "BOARD_ID")
private Board board;
private String content;
}
BoardDetail처럼 식별자가 단순히 컬럼 하나면 @MapsId를 사용하고 속성 값은 비워두면 된다. 이때 @MapsId는 @Id를 사용해서 식별자로 지정한 BoardDetail.boardId와 매핑된다.
private static void save(EntityManager entityManager){
Board board = new Board();
board.setTitle("제목");
entityManager.persist(board);
BoardDetail boardDetail = new BoardDetail();
boardDetail.setContent("내용");
boardDetail.setBoard(board);
entityManager.persist(boardDetail);
}
위의 코드는 일대일 식별 관계를 저장 하는 코드이다.