Spring/Spring JPA

[JPA] @OneToOne

개발자잡 2024. 11. 25. 09:14

@OneToOne은 JPA에서 두 엔티티 간의 1:1 관계를 매핑하기 위해 사용하는 어노테이션입니다. 이는 관계형 데이터베이스의 1:1 관계를 표현하며, 두 테이블의 데이터가 서로 정확히 하나씩 연결되는 경우에 사용됩니다.

주요 특징

  1. 1:1 관계 매핑:
    • 각 엔티티 인스턴스는 다른 엔티티의 인스턴스와 정확히 하나씩 매핑됩니다.
    • 예를 들어, User 엔티티와 Profile 엔티티가 있을 때, 각 사용자는 하나의 프로필만 가질 수 있으며, 각 프로필은 하나의 사용자에만 속합니다.
  2. 연결 방식:
    • 외래 키(Foreign Key)를 통해 연결됩니다.
    • 관계를 주도하는 "소유 측(owner side)"와 "비소유 측(non-owner side)"로 나뉩니다.
  3. 지연 로딩:
    • 기본적으로 @OneToOne 관계는 FetchType.EAGER로 설정됩니다.
    • 필요에 따라 @OneToOne(fetch = FetchType.LAZY)로 변경해 사용할 수 있습니다.

 

주요 속성

  1. mappedBy:
    • 관계의 주도권을 설정합니다.
    • 소유 측이 아닌 엔티티에서 외래 키를 매핑할 필드를 지정합니다.
  2. fetch:
    • 관계를 가져올 때 데이터를 로드하는 방식을 설정합니다.
      • FetchType.EAGER: 즉시 로딩 (기본값).
      • FetchType.LAZY: 지연 로딩.
  3. cascade:
    • 연관된 엔티티의 상태를 전이할지 설정합니다.
    • 예: CascadeType.ALL, CascadeType.PERSIST, CascadeType.REMOVE 등.
  4. optional:
    • 연관된 엔티티가 필수인지 여부를 설정합니다.
    • 기본값은 true로, 연관된 엔티티가 없어도 허용합니다.

예제 1. 외래 키를 사용한 1:1 매핑

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "profile_id", referencedColumnName = "id") // 외래 키 매핑
    private Profile profile;
}

@Entity
public class Profile {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String bio;
}

User 엔티티는 Profile 엔티티와 1:1 관계를 가지며, profile_id 외래 키를 통해 연결됩니다.

 

예제 2) 양방향 1:1 매핑

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
    private Profile profile;
}

@Entity
public class Profile {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String bio;

    @OneToOne
    @JoinColumn(name = "user_id") // 외래 키 정의
    private User user;
}

 

  • User가 "비소유 측", Profile이 "소유 측"으로 정의됩니다.
  • mappedBy는 Profile 엔티티의 필드 이름을 가리킵니다.

실제 SQL 예시

위의 User와 Profile 예제를 기준으로 생성되는 SQL 테이블 구조:

 

CREATE TABLE User (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255),
    profile_id BIGINT,
    FOREIGN KEY (profile_id) REFERENCES Profile(id)
);

CREATE TABLE Profile (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    bio VARCHAR(255)
);

주요 활용 예

  1. 회원과 프로필:
    • 회원(User) 테이블이 프로필(Profile) 테이블과 1:1로 매핑될 때.
  2. 주문과 배송 정보:
    • 주문(Order) 테이블이 배송 정보(ShippingInfo) 테이블과 1:1로 매핑될 때.

주의점

  1. 외래 키 관리:
    • 외래 키를 어느 쪽에서 관리할지 명확히 정의해야 합니다.
  2. 성능:
    • 기본 FetchType.EAGER는 데이터가 항상 즉시 로드되므로 성능에 영향을 줄 수 있습니다. 필요에 따라 FetchType.LAZY를 설정하세요.

정리

@OneToOne은 1:1 관계를 명확히 표현하며, 관계형 데이터베이스 설계와 객체 지향 설계의 일관성을 유지하는 데 유용합니다.