본문 바로가기
독서/스프링 부트 핵심 가이드

[스프링 부트 핵심 가이드] Chapter 9장. 연관 관계 매핑

by JayAlex07 2023. 9. 24.

스프링 부트 핵심 가이드

img

 

[스프링 부트 핵심 가이드] Chapter 9장. 연관 관계 매핑

 

RDBMS를 사용할 때에 한 테이블을 가지고 모든 기능을 구현하기 불가능 하다

 

즉 여러 테이블을 이용하고, 연결하여 기능을 구현한다

  • One To One : 일대일 (1:1)
  • One To Many : 일대다 (1:N)
  • Many To One : 다대일 (N:1)
  • Many To Many : 다대다 (N:M)

 

 

일대일 매핑

 

 

일대일 단방향 매핑

@Entity
@Table(name="MEMBER")
@Getter
@Setter
@NoArgsConstructor
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long memberId;

    private String username;

    @OneToOne
    @JoinColumn(name="LOCKER")
    private Locker locker;
}
  • @OneToOne 어노테이션을 통해서 다른 엔티티 객체를 필드로 정의했다
    • optional = false : 해당 칼럼에 null인 값을 허용하지 않게 된다 (기본은 true로 되어 있다)
  • @JoinColumn 어노테이션은 기본값이 설정 되어 있어 자동으로 이름을 매핑하지만 의도한 이름이 들어가지 않기 때문에 name 속성을 사용해 원하는 칼럼명을 지정할 수 있다

 

@JoinColumn 속성

  • name : 매핑할 외래키의 이름을 설정
  • referencedColumnName : 외래키가 참조할 상대 테이블의 칼럼명을 지정
  • foreignkey : 외래키를 생성하면서 지정할 제약조건을 설정 (unique, nullable, insertable, updatable 등)

 

일대일 양방향 매핑

  • 위에 코드도 같이 봐야 한다
  • 즉 두 엔티티 모두 @OneToOne 어노테이션을 가지고 있다
@Entity
@Table(name="LOCKER")
@Getter
@Setter
@NoArgsConstructor
public class Locker {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long memberId;

    private String name;

    @OneToOne(mappedBy = "LOCKER")
    private Member member;
}
  • mappedby는 어떤 객체가 주인인지 표시하는 속성이다
    • 데이터베이스의 연관관계를 반영해서 한 쪽의 테이블에서만 외래키를 바꿀 수 있도록 정하는 것이다
    • 즉 양방향으로 매핑하되 한쪽에게만 외래키를 주는 것이다

 

 

다대일, 일대다 매핑

 

같은 개념이고, 하나의 값이 여러 개를 매핑하는 것이다

  • '나' 라는 사람이 있고, '나'는 여러 개의 핸드폰을 소유 할 수 있다

 

 

다대일 단방향 매핑

@Entity
@Table(name="Member")
@Getter
@Setter
@NoArgsConstructor
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long memberId;

    private String username;

    @ManyToOne
    @JoinColumn(name="team_id")
    private Team team;
}
  • 일반적으로 외래키를 가지고 있는 쪽이 주인 역할을 한다
    • 즉 위에는 member가 team 엔티티의 주인이 된다

 

 

다대일 양방향 매핑

@Entity
@Table(name="Team")
@Getter
@Setter
@NoArgsConstructor
public class Team {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long teamId;

    private String name;

    @OneToMany(mappedBy = "Team", fetch = FetchType.EAGER)
    private List<Member> memberList = new ArrayList<>();
}
  • 반대로 한 팀 당 여러 명의 멤버가 있음으로 일대다 즉 @OneToMany 어노테이션을 사용한다
  • 여러 맴버 엔티티가 포함될 수 있어 리스트 형식으로 필드를 생성한다
  • fetch = FetchType.EAGER 는 @OneToMany의 기본 fetch 전략이 Lazy이기 때문에 즉시 로딩으로 조정한다
자연로딩과 즉시로딩
- 연관관계와 상관없이 즉각 해당 엔티티의 값만 조회하고 싶거나 연관관계를 가진 테이블의 값도 조회하고 싶은 경우 등 여러 조건들을 만족하기 위해 등장한 개념이다

 

 

일대다 단방향 매핑

  • @OneToMany를 사용하는 입장에서는 어느 엔티티 클래스도 연관관계의 주인이 될 수 없다
@Entity
@Table(name="Team")
@Getter
@Setter
@NoArgsConstructor
public class Team {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long teamId;

    private String name;

    @OneToMany(mappedBy = "Team", fetch = FetchType.EAGER)
    @JoinColumn(name = "member_id")
    private List<Member> memberList = new ArrayList<>();
}
  • @OneToMany와 @JoinColumn을 사용하면 상품 엔티티에서 별도의 설정을 하지 않아도 일대다 단방향 연관관계가 매핑된다
    • @JoinColumn은 필수 사항이 아니다

 

 

다대다 매핑

 

실무에서는 거의 사용이 안 되는 구성이다

 

교차 엔티티라고 부르는 중간 테이블을 생성해서 다대다 관계를 일대다 또는 다대일 관계로 해소한다

 

 

영속성 전이

 

특정 엔티티의 영속성 상태를 변경할 때 그 엔티티와 연관된 엔티티의 영속성에도 영향을 미쳐 영속성 상태를 변경하는 것을 의미한다

 

영속성 전이 타입

종류 설명
ALL 모든 영속 상태 변경에 대해 영속성 전이를 적용
PERSIST 엔티티가 영속화할 때 연관된 엔티티도 함께 영속화
MERGE 엔티티를 영속성 컨텍스트에 병합할 때 연관된 엔티티도 병합
REMOVE 엔티티를 제거할 때 연관된 엔티티도 제거
REFRESH 엔티티를 새로고침할 때 연관된 엔티티도 새로고침
DETACH 엔티티를 영속성 컨텍스트에서 제외하면 연관된 엔티티도 제외
  • 영속성 전이에 사용되는 타입은 엔티티 생명주기와 연관이 있다
  • cascade (영속성 전이) 요소의 값으로 주어진 영속 상태의 변경이 일어나면 매핑으로 연관된 엔티티에도 동일한 동작이 일어나도록 전이를 발생시킨다