1. 개요

이 튜토리얼에서는 JPA에서 일대일 매핑을 만드는 다양한 방법을 살펴 보겠습니다.

우리는 Hibernate 프레임 워크에 대한 기본적인 이해가 필요합니다. 그래서  추가적인 배경 지식을 위해 Hibernate 5 with Spring 가이드를 확인하십시오 .

2. 설명

사용자 관리 시스템을 구축하고 있고 상사가 각 사용자의 우편 주소를 저장하도록 요청한다고 가정 해 보겠습니다. 사용자는 하나의 우편 주소를 가지며 우편 주소에는 한 명의 사용자 만 연결됩니다.

이것은 사용자 주소  엔터티 간의 일대일 관계의 예입니다  .

다음 섹션에서이를 구현하는 방법을 살펴 보겠습니다.

3. 외래 키 사용

3.1. 외래 키로 모델링

외래 키 기반 일대일 매핑을 나타내는 다음 ER 다이어그램을 살펴 보겠습니다 .

address_id 외래 키를 통해 사용자를 주소에 매핑하는 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 의)  주소 받는 외래 키 같은 테이블  사용자  테이블 :

동일한 기본 키 값을 공유하는 주소에 연결된 사용자가있는 ER 다이어그램

이러한 엔터티가 일대일 관계를 가지고 있다는 사실을 활용하여 저장 공간을 최적화했습니다.

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 값을 제거하는 데 도움이 될 수 있습니다 .

조인 테이블을 통해 직원을 워크 스테이션에 연결하는 ER 다이어그램

이제 관계가있을 때마다 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 에서 찾을 수 있습니다 .