본문 바로가기

Spring/JPA

JPA- 다대일, 일대일

연관관계 주인 정리

기본 설명

 

다대일

연관관계 주인은 외래키를 가지고 있는 객체가 된다.

외래키를 가지는 객체는 多인 엔티티이다. 따라서 여기서는 Member가 多이므로 Member.team이 연관관계 주인이된다.

@Entity
public class Member {

    @Id @GeneratedValue 
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "USERNAME", nullable = false)
    private String userName;

    @ManyToOne
    @JoinColumn(name = "TEAM_ID")  //연관관계 주인
    private Team team;
    
    // 연관관계 편의 매소드
    public void changeTeam(Team team) {
        this.team = team;
        team.getMembers().add(this);
    }
}

 양방향은 사실 단방향이 두개인 것이다. 연관관계 주인의 경우 단방향에서 구현한대로 똑같이 하면되고, 양방향을 구현하기 위해선 연관관계 주인이 아닌 객체도 주인 객체의 필드에 매핑을 해주어야 서로서로 조회할 수 있으므로 리스트로 필드를 만들고  @OneToMany(mappedBy = "주인 객체")로 매핑하여 읽기 전용으로 만들어준다. 

@Entity
public class Team {

    @Id
    @GeneratedValue
    @Column(name = "TEAM_ID")
    private Long id;
    private String name;

    @OneToMany(mappedeBy = "team")  // members로는 조회만 가능. Member.team이 연관관계 주인
    private List<Member> members = new ArrayList<>();
}

 

일대일

일대일 관계

 - 단방향

\

 다대일과 유사하다. 주 테이블 하나 정해서 외래키 주고 연관관계 주인으로 만든다. 

@Entity
public class Member {  // 주테이블 MEMBER

    @Id  
    @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "USERNAME", nullable = false)  // 매핑할 컬럼명이 "USERNAME". + not null 설정
    private String userName;

    @OneToOne
    @JoinColumn(name = "LOCKER_ID")  //연관관계 주인
    private Locker locker;  
}

 

+α) 주 테이블 정하는 방법

예시

주 테이블은 주로 많이 접근하는 테이블을 사용한다. 

위의 경우에는 Order와 Delivery가 일대일 관계인데 보통 Order를 많이 찾으니 fk를 Order에게 두고, 주인을 Order.delivery로 정하면 된다.

 

 Order.class

package jpabook.jpashop.domain;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Entity
@Getter @Setter
public class Order {
    @Id
    @GeneratedValue
    @Column(name = "order_id")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "member_id")
    private Member member;

    @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
    private List<OrderItem> orderItems = new ArrayList<>();

    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "delivery_id")
    // 꿀팁! OneToOne일때 주인 지정: 많이 사용하는 놈한테 주인설정을 준다.
    private Delivery delivery;

    private LocalDateTime orderDate;

    @Enumerated(EnumType.STRING)
    private OrderStatus status;
}

 Delivery.class

package jpabook.jpashop.domain;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;

@Entity
@Getter @Setter
public class Delivery {

    @Id
    @GeneratedValue @Column(name = "delivery_id")
    private Long id;

    @OneToOne(mappedBy = "delivery", fetch = FetchType.LAZY)
    // Order.delivery가 주인, Delivery.order는 mappedBy 된다.
    private Order order;

    @Embedded
    private Address address;

    @Enumerated(EnumType.STRING)
    private DeliveryStatus status;
}

 

- 양방향

@Entity
public class Locker {  // 대상 테이블 LOCKER

    @Id @GeneratedValue
    @Column(name = "LOCKER_ID")
    private Long id;
    private String name;

    @OneToOne(mappedBy = "locker")  // 읽기 전용
    private Member member;
}

주 테이블의 반대편(대상테이블)은 mappedBy 적용.

  • 대상 테이블은 다대일중 일인 테이블처럼 mappedBy해주면 된다.

'Spring > JPA' 카테고리의 다른 글

JPA- @MappedSuperClass  (0) 2023.03.12
JPA- 상속관계 매핑  (0) 2023.03.12
JPA- 연관관계 매핑 주의점  (0) 2023.03.05
JPA- 연관관계 매핑  (0) 2023.03.05
JPA- 중요! 엔티티 매핑  (0) 2023.02.28