[JPA 프로그래밍] 4. 연관관계 매핑

반응형
728x90
반응형

JPA 연관관계 키워드

키워드 설명
방향 (Direction) - 단방향, 양방향이 있다.
- 단방향 관계 : 회원과 팀의 관계가 있을때 회원 -> 팀 또는 팀 -> 회원 중 한쪽만 참조하는 것
- 양방향 관계 : 회원 -> 팀, 팀 -> 회원 양쪽 모두 서로 참조하는 것
- 방향은 객체 관계에서만 존재하고 테이블 관계는 항상 양방향이다.
다중성 (Multiplicity) - 다대일(N:1), 일대다(1:N), 일대일(1:1), 다대다(N:M) 이 있다.
연관관계의 주인 (owner) - 객체를 양방향 연관관계로 만들면 연관관계의 주인을 정해야한다.

 

 

단방향 연관관계

https://velog.io/@asdfg5415/%EC%97%B0%EA%B4%80-%EA%B4%80%EA%B3%84-%EB%8B%A8%EB%B0%A9%ED%96%A5-%EC%96%91%EB%B0%A9%ED%96%A5

 

객체 연관관계

회원 객체는 Member.team 필드(멤버변수)로 팀 객체와 연관관계를 맺는다.

회원 객체와 팀 객체는 단방향 관계다. 

회원은 Member.team 필드를 통해서 팀을 알 수 있지만, 반대로 팀은 회원을 알 수 없다.

 

테이블 연관관계

회원 테이블은 TEAM_ID 외래 키로 팀 테이블과 연관관계를 맺는다.

회원 테이블과 팀 테이블은 양방향 관계이다. 

 

객체 연관관계와 테이블 연관관계의 차이

참조를 통한 연관관계는 언제나 단방향이다. 객체간에 연관관계를 양방향으로 만들고 싶으면 반대쪽에도 필드를 추가해서 참조를 보관해야한다. 이렇게 양쪽에서 서로 참조하는 것을 양방향 연관관계라고 하는데, 이것은 정확히 말하자면 서로 다른 단방향 관계 2개다. 

 

반면에 테이블은 외래 키 하나로 양방향으로 조인할 수 있다. 

 

단방향 연관관계
class A {
    B b;
}

class B {}

 

양방향 연관관계
class A {
    B b;
}

class B {
    A a;
}

 

객체 관계 매핑
  • Member.java
import lombok.*;

import javax.persistence.*;


@Entity
public class Member {
    @Id
    @Column(name= "ID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "NAME", nullable = false, length = 10)
    private String username;

    @ManyToOne // member 테이블에 team_id varchar(255), 설정
    @JoinColumn(name="TEAM_ID") // 매핑할 외래 키 이름을 지정한다.
    private Team team;

    ...
}

 

  • Team.java
import lombok.*;

import javax.persistence.*;
import java.util.List;

@Entity
public class Team {
    @Id
    @Column(name= "ID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "NAME", nullable = false, length = 10)
    private String name;

    ...
}

 

1) 객체 연관관계 : 회원 객체의 Member.team 필드 사용

2) 테이블 연관관계 : 회원 테이블의 MEMBER.TEAM_ID 외래 키 컬럼을 사용

 

 

Member.java

@ManyToOne // member 테이블에 team_id varchar(255), 설정
@JoinColumn(name="TEAM_ID") // 매핑할 외래 키 이름을 지정한다.
private Team team;

1) @ManyToOne

다대일(N:1) 관계라는 매핑 정보다. 회원과 팀은 다대일 관계이다.

 

2) @JoinColumn(name="TEMA_ID")

조인 컬럼은 외래 키를 매핑할때 사용한다. name 속성에 매핑할 외래 키 이름을 지정한다. 회원과 팀 테이블은 TEAM_ID 외래 키로 연관관계를 맺으므로 이 값을 지정하면 된다. 

 

3) 테이블 생성 쿼리

create table member (
    id varchar(255) not null,
    name varchar(10) not null,
    team_id varchar(255),
    primary key (id)
)

create table team (
    id int8 not null,
    name varchar(10) not null,
    primary key (id)
)

 

 

 

 

양방향 연관관계

https://velog.io/@asdfg5415/%EC%97%B0%EA%B4%80-%EA%B4%80%EA%B3%84-%EB%8B%A8%EB%B0%A9%ED%96%A5-%EC%96%91%EB%B0%A9%ED%96%A5
https://velog.io/@asdfg5415/%EC%97%B0%EA%B4%80-%EA%B4%80%EA%B3%84-%EB%8B%A8%EB%B0%A9%ED%96%A5-%EC%96%91%EB%B0%A9%ED%96%A5

 

- 회원 -> 팀 (member.team)
- 팀 -> 회원 (Team.members)

 

  • Member.java
import lombok.*;

import javax.persistence.*;


@Entity
public class Member {
    @Id
    @Column(name= "ID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "NAME", nullable = false, length = 10)
    private String username;

    @ManyToOne // member 테이블에 team_id varchar(255), 설정
    @JoinColumn(name="TEAM_ID") // 매핑할 외래 키 이름을 지정한다.
    private Team team;

    ...
}

 

  • Team.java
package com.book.jpa.chapter05;

import lombok.*;

import javax.persistence.*;
import java.util.List;

@Entity
public class Team {
    @Id
    @Column(name= "ID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "NAME", nullable = false, length = 10)
    private String name;

    @OneToMany
    private List<Member> members;
     
}

 

1) 테이블 생성 쿼리

create table member (
    id varchar(255) not null,
    name varchar(10) not null,
    team_id varchar(255),
    primary key (id)
)

create table team_members (
    team_id int8 not null,
    members_id int8 not null
)

create table team (
    id int8 not null,
    name varchar(10) not null,
    primary key (id)
)

 

Team.java 에 mappedBy 속성을 추가해보자.

mappedBy 속성

양방향 매핑일때 사용한다. 반대쪽 매핑의 필드 이름을 값으로 주면 된다.

반대쪽 매핑이 Member.team이므로 team을 값으로 주었다. 

 

 

  • Team.java
import lombok.*;

import javax.persistence.*;
import java.util.List;

@Entity
public class Team {
    @Id
    @Column(name= "ID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(name = "NAME", nullable = false, length = 10)
    private String name;

    @OneToMany(mappedBy = "team") // team 은 주인이 아님을 설장한다. 주인은 Member.team 이다.
    private List<Member> members;
     
}

 

1) 테이블 생성 쿼리

create table member (
    id varchar(255) not null,
    name varchar(10) not null,
    team_id varchar(255),
    primary key (id)
)

create table team (
    id int8 not null,
    name varchar(10) not null,
    primary key (id)
)

 

 

연관관계의 주인

객체에는 양방향 관계라는 것이 없다. 서로 다른 단방향 연관관계 2개를 애플리케이션 로직으로 잘 묶어서 양방향인 것처럼 보이게 할 뿐이다. 테이블은 외래 키 하나로 두 테이블의 연관관계를 관리하는데, 엔티티를 단방향으로 매핑하면 참조를 하나만 사용하므로 이 참조로 외래키를 관리하면 된다. 

 

근데 엔티티를 양방향으로 매핑하면 회원 -> 팀, 팀 -> 회원 두 곳에서 서로를 참조한다. 따라서 객체의 연관관계를 관리하는 포인트는 2곳으로 늘어난다. 엔티티를 양방향 연관관계를 설정하면 객체의 참조는 둘인데 외래 키는 하나다. 이 중 어떤 관계를 사용해서 외래키를 관리하는 곳을 정해야하고, 이를 연관관계의 주인(Owner)이라고 한다.

 

어떤 연관관계 주인으로 정할지는 mappedBy 속성을 사용하면 된다.

  • 주인은 mappedBy 속성을 사용하지 않는다.
  • 주인이 아니면 mappedBy 속성을 사용해서 속성의 값으로 연관관계의 주인을 지정해야한다.

 

  

 

반응형

Designed by JB FACTORY