위와 같이 Post클래스와 PostDetails클래스가 있다고 하자.
@MapsId
를 활용하지 않은 1:1 매핑@MapsId
를 활용한 1:1 매핑이 2가지에 대해 설명하고자 한다.
[PostDetails]
@Entity(name = "PostDetails")
@Table(name = "post_details")
public class PostDetails {
@Id
@GeneratedValue
private Long id;
@Column(name = "created_on")
private Date createdOn;
@Column(name = "created_by")
private String createdBy;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "post_id")
private Post post;
public PostDetails() {}
public PostDetails(String createdBy) {
createdOn = new Date();
this.createdBy = createdBy;
}
//Getters and setters omitted for brevity
}
[Post]
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
@GeneratedValue
private Long id;
private String title;
@OneToOne(mappedBy = "post", cascade = CascadeType.ALL,
fetch = FetchType.LAZY, optional = false)
private PostDetails details;
//Getters and setters omitted for brevity
public void setDetails(PostDetails details) {
if (details == null) {
if (this.details != null) {
this.details.setPost(null);
}
}
else {
details.setPost(this);
}
this.details = details;
}
}
위의 코드처럼 매핑을 한 경우 DB에서는 다음과 같이 테이블이 생성된다.
여기서 효율적이지 않음을 느껴야 하는데 왜냐하면 어차피 1:1 관계이므로
post테이블의 PK와 post_details의 PK가 서로 미러링하도록 하는 것이 더 좋기 때문이다.
그래서 테이블이 다음과 같이 설계가 되어야 효율적일 것이다.
이렇게 하면 post_details의 PK가 FK도 되며 두 테이블의 PK를 공유하게 된다.
그렇다면 위의 테이블처럼 설계되었을 때 어떻게 매핑을 해야할까?
바로 이것이 @MapsId
를 활용한 1:1 매핑이다.
[PostDetails] -> [Post]는 위의 코드와 같다.
@Entity(name = "PostDetails")
@Table(name = "post_details")
public class PostDetails {
@Id
private Long id;
@Column(name = "created_on")
private Date createdOn;
@Column(name = "created_by")
private String createdBy;
@OneToOne(fetch = FetchType.LAZY)
@MapsId
private Post post;
public PostDetails() {}
public PostDetails(String createdBy) {
createdOn = new Date();
this.createdBy = createdBy;
}
//Getters and setters omitted for brevity
}
@MapsId
를 추가함으로써 Post의 id와 PostDetails의 id가 미러링된다.
-> 어차피 Post의 id 값을 가져오므로 @GeneratedValue가 필요없어지게 된다.
@MapsId
를 추가함으로써 FK가 PK의 역할을 하게된다.