1. 개요
이 튜토리얼에서는 JPA에서 일대일 매핑을 만드는 다양한 방법을 살펴 보겠습니다.
우리는 Hibernate 프레임 워크에 대한 기본적인 이해가 필요합니다. 그래서 추가적인 배경 지식을 위해 Hibernate 5 with Spring 가이드를 확인하십시오 .
2. 설명
사용자 관리 시스템을 구축하고 있고 상사가 각 사용자의 우편 주소를 저장하도록 요청한다고 가정 해 보겠습니다. 사용자는 하나의 우편 주소를 가지며 우편 주소에는 한 명의 사용자 만 연결됩니다.
이것은 사용자 와 주소 엔터티 간의 일대일 관계의 예입니다 .
다음 섹션에서이를 구현하는 방법을 살펴 보겠습니다.
3. 외래 키 사용
3.1. 외래 키로 모델링
외래 키 기반 일대일 매핑을 나타내는 다음 ER 다이어그램을 살펴 보겠습니다 .
이 예에서, address_id 에서 열 사용자 는 IS 외래 키 에 주소 .
3.2. JPA에서 외래 키로 구현
먼저 User 클래스를 만들고 적절하게 어노테이션을 달아 보겠습니다 .
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
//...
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "address_id", referencedColumnName = "id")
private Address address;
// ... getters and setters
}
참고 것을 우리는 배치 @OneToOne의 어노테이션 , 관련 개체 필드를 주소 .
또한 주소 테이블 의 기본 키에 매핑 되는 사용자 테이블 의 열 이름을 구성 하려면 @JoinColumn 어노테이션 을 배치해야 합니다. 이름을 제공하지 않으면 Hibernate는 몇 가지 규칙 에 따라 기본 이름 을 선택합니다.
마지막으로 다음 엔터티에서 @JoinColumn 어노테이션을 사용하지 않을 것입니다. 이는 외래 키 관계의 소유 측에서만 필요하기 때문입니다. 간단히 말해, 외래 키 열을 소유 한 사람은 @JoinColumn 어노테이션을받습니다.
주소 실체가 밖으로 조금 더 간단집니다 :
@Entity
@Table(name = "address")
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
//...
@OneToOne(mappedBy = "address")
private User user;
//... getters and setters
}
여기에도 @OneToOne 어노테이션 을 배치해야합니다 . 이것은 양방향 관계 이기 때문 입니다. 관계의 주소 쪽을 비 소유 쪽이라고합니다.
4. 공유 기본 키 사용
4.1. 공유 기본 키로 모델링
이 전략에서는, 대신에 새로운 열 만드는 address_id을 , 우리는 기본 키를 표시합니다 열 ( USER_ID 의) 주소 받는 외래 키 같은 테이블 사용자 테이블 :
이러한 엔터티가 일대일 관계를 가지고 있다는 사실을 활용하여 저장 공간을 최적화했습니다.
4.2. JPA에서 공유 기본 키로 구현
정의는 약간만 변경됩니다.
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
//...
@OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
@PrimaryKeyJoinColumn
private Address address;
//... getters and setters
}
@Entity
@Table(name = "address")
public class Address {
@Id
@Column(name = "user_id")
private Long id;
//...
@OneToOne
@MapsId
@JoinColumn(name = "user_id")
private User user;
//... getters and setters
}
mappedBy의 속성은 이제로 이동 사용자 외래 키는 현재에 존재하기 때문에 클래스 주소 테이블. 또한 User 엔터티 의 기본 키가 연결된 Address 엔터티에 대한 외래 키 값으로 사용됨 을 나타내는 @PrimaryKeyJoinColumn 어노테이션을 추가 했습니다 .
여전히 Address 클래스 에 @Id 필드 를 정의해야합니다 . 그러나 이것은 user_id 열을 참조하며 더 이상 @GeneratedValue 어노테이션을 사용하지 않습니다 . 또한 User 를 참조하는 필드 에 기본 키 값이 User 엔터티 에서 복사됨을 나타내는 @MapsId 어노테이션을 추가 했습니다 .
5. 조인 테이블 사용
일대일 매핑은 선택 및 필수의 두 가지 유형일 수 있습니다. 지금까지는 필수 관계 만 보았습니다.
이제 우리 직원이 워크 스테이션과 연결되어 있다고 가정 해 보겠습니다. 일대일이지만 때로는 직원이 워크 스테이션을 가지고 있지 않을 수 있으며 그 반대의 경우도 마찬가지입니다.
5.1. 조인 테이블로 모델링
지금까지 논의한 전략은 선택적 관계를 처리하기 위해 열에 null 값을 입력하도록 강제합니다.
일반적으로 조인 테이블을 고려할 때 다 대다 관계 를 생각 하지만이 경우 조인 테이블을 사용하면 이러한 null 값을 제거하는 데 도움이 될 수 있습니다 .
이제 관계가있을 때마다 emp_workstation 테이블에 항목을 만들고 null을 완전히 피 합니다.
5.2. JPA에서 조인 테이블로 구현
첫 번째 예에서는 @JoinColumn을 사용했습니다 . 이번에는 @JoinTable을 사용합니다 .
@Entity
@Table(name = "employee")
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
//...
@OneToOne(cascade = CascadeType.ALL)
@JoinTable(name = "emp_workstation",
joinColumns =
{ @JoinColumn(name = "employee_id", referencedColumnName = "id") },
inverseJoinColumns =
{ @JoinColumn(name = "workstation_id", referencedColumnName = "id") })
private WorkStation workStation;
//... getters and setters
}
@Entity
@Table(name = "workstation")
public class WorkStation {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
//...
@OneToOne(mappedBy = "workStation")
private Employee employee;
//... getters and setters
}
@ JoinTable 은 Hibernate에게 관계를 유지하면서 조인 테이블 전략을 사용하도록 지시합니다.
또한 Employee 는 조인 테이블 어노테이션을 사용하기로 선택 했으므로이 관계의 소유자입니다.
6. 결론
이 기사에서 우리는 JPA와 Hibernate에서 일대일 연관을 유지하는 다양한 방법과 각각을 사용할시기를 배웠습니다.
이 기사의 소스 코드는 GitHub 에서 찾을 수 있습니다 .