일대일 관계는 엔티티 하나가 다른 엔티티 한 개와 관계를 가지는 연관관계입니다. 예를들어 학생증을 받으면 학생증은 하나의 학생에서 대해서만 유효하고 반대로 학생도 본인에게 유효한 학생증 하나만을 사용할 수 있습니다.
이처럼 일대일 관계에서 그 반대 연관관계도 항상 일대일 연관관계가 유지됩니다.
지난 포스트에서 다대일을 다루면서 다대일 연관관계의 주인은 항상 다 쪽이 가져간다고 했었는데요. 일대일 연관관계에서는 어느 쪽이든 외래 키를 가진 주인이 될 수 있습니다.
위 테이블 구조에서 학생 테이블이 주인 테이블 되고 학생증 테이블이 대상 테이블이 됩니다. 그리고 외래 키를 주인 테이블인 학생 테이블에 넘겨주었습니다.
이 방식은 주인 테이블을 통해 대상 테이블을 참조할 수 있어서 객체지향 프로그래밍과 같은 느낌으로 사용할 수 있습니다.
@Entity
@Table(name = "students_table")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "s_id", nullable = false)
private Long id;
@OneToOne(fetch = FetchType.LAZY) // 단방향 1:1
@JoinColumn(name = "sic_id", nullable = false, unique = true)
private StudentIdCard studentIdCard;
// 생성자 및 getter
}
@Entity
@Table(name = "student_id_cards_table")
public class StudentIdCard {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "sic_id", nullable = false)
private Long id;
// 생성자 및 getter
}
단방향이므로 주인 엔티티 쪽에만 연관관계 매핑 정보(@OneToOne)을 사용합니다.
@Entity
@Table(name = "students_table")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "s_id", nullable = false)
private Long id;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "sic_id", nullable = false, unique = true)
private StudentIdCard studentIdCard;
//생성자 및 getter
}
@Entity
@Table(name = "student_id_cards_table")
public class StudentIdCard {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "sic_id", nullable = false)
private Long id;
@OneToOne(mappedBy = "studentIdCard", fetch = FetchType.LAZY)
private Student student;
//생성자 및 getter
}
외래 키를 가진 학생 테이블이 주인 테이블(엔티티)이므로 대상 엔티티인 학생증 엔티티에 mappedBy 속성을 반드시 명시해줍니다.
이번엔 반대로 대상 테이블에 외래 키를 넘겨준 상황입니다.
이 방식은 테이블 관계가 일대다로 변경되는 상황에서 테이블 구조를 유지할 수 있다는 장점이 있습니다.
JPA는 대상 테이블이 외래 키를 가진 단방향 일대일 연관관계 매핑은 지원하지 않습니다.
그래서 이 경우에 단방향 일대일 연관관계를 매핑하고 싶다면 학생증 테이블(엔티티)를 주인처럼 취급하도록 하거나(위 단방향 예시에서 @OneToOne 매핑을 학생 대신 학생증 엔티티에 사용) 양방향 연관관계를 사용해야합니다.
@Entity
@Table(name = "students_table")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "s_id", nullable = false)
private Long id;
@OneToOne(mappedBy = "student", fetch = FetchType.LAZY)
private StudentIdCard studentIdCard;
//생성자 및 getter
}
@Entity
@Table(name = "student_id_cards_table")
public class StudentIdCard {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "sic_id", nullable = false)
private Long id;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "s_id", nullable = false, unique = true)
private Student student;
//생성자 및 getter
}
기존 양방향의 매핑만 바꿔서 사용하시면 됩니다.