연관관계 매핑(2) - 단방향, 양방향

2024. 1. 4. 23:36spring/JPA

객체는 참조를 사용해서 관계를 맺고 테이블은 외래 키를 사용해서 관계를 맺는다.

객체의 참조와 테이블의 외래 키를 매핑하는 것이 이 장의 목표다.

 

1. 단방향 연관관계

요구조건

 1) 회원과 팀이 있다.

 2) 회원은 하나의 팀에만 소속될 수 있다.

 3) 회원과 팀은 다대일 관계다.

 

객체 연관관계

 - 회원 객체는 Member.team 필드로 팀 객체와 연관 관계를 맺는다.

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

 

테이블 연관관계

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

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

 

객체 연관관계와 테이블 연관관계의 가장 큰 차이

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

 

 

1.1. 객체 관계 매핑

 

 

매핑한 회원 엔티티

@Entity
public class Member {
    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;
    @Column(name = "USERNAME")
    private String username;

    @ManyToOne
    @JoinColumn(name = "TEAM_ID")
    private Team team;
    
    //getter, setter
    
}

 

매핑한 팀 엔티티

@Entity
public class Team {

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

    //getter, setter
}

 

 

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

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

@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;

 

@ManyToOne: 이름 그대로 N:1 관계라는 매핑 정보다. 연관관계를 매핑할 때 이렇게 다중성을 나타내는 어노테이션을 필수로 사용해야 한다.

@JoinColumn(name="TEAM_ID") : 조인 컬럼은 외래 키를 매핑할 때 사용한다. name 속성에는 매핑할 외래 키 이름을 지정한다. 이 어노테이션은 생략할 수 있다.

 

@JoinColumn

속성 기능 기본값
name 매핑할 외래 키 이름 필드면 + _ + 참조하는 테이블의 기본 키 컬럼명
referencedColumnName 외래 키가 참조하는 대상 테이블의 컬럼명 참조하는 테이블의 기본키 컬럼명
foreignKey(DDL) 외래 키 제약조건을 직접 지정한다.  

 

@ManyToOne

속성 기능 기본값
optional false로 설정하면 연관된 엔티티가 항상 있어야 한다. true
fetch 글로벌 페치 전략을 설정한다. @ManyToOne=FetchType.EAGER
@OneToMany=FetchType.LAZY
cascade 영속성 전이 기능을 사용한다.  
targetEntity 연관된 엔티티의 타입 정보를 설정한다.  

 

 

 

2. 양방향 연관관계

위에서는 회원에서 팀으로만 접근하는 다대일 단방향 캐핑을 했다. 이번에는 반대 반향인 팀에서 회원으로 접근하는 관계를 추가하자.

 

매핑환 회원 엔티티

@Entity
public class Member {
    @Id @GeneratedValue
    @Column(name = "MEMBER_ID")
    private Long id;
    @Column(name = "USERNAME")
    private String username;

    @ManyToOne
    @JoinColumn(name = "TEAM_ID")
    private Team team;
    
    //getter, setter
    
}

 

매핑한 팀 엔티티

@Entity
public class Team {

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

    @OneToMany(mappedBy = "team")
    private List<Member> members = new ArrayList<>();

	//Getter, Setter
}

 

팀과 회원은 일대다 관계다. 따라서 팀 엔티티에 컬렉션인 List<Member> members를 추가한다. 일대다 관계를 매핑하기 위해 @OneToMany 매핑정보를 사용했다. mappedBy 속성은 양방향 매핑일 때 사용하는데 반대쪽 매핑의 필드 이름을 값으로 주면 된다. 팀은 연관관계의 주인이 아닌 관계로 mappedBy 속성을 줬다.

 

2.1 연관관계의 주인

@OneToMany는 직관적이지만 mappedBy 속성은 무언인가? 할 수 있다. 테이블은 외래 키 하나로 양쪽이 서로 조인할 수 있다. 엔티티는 참조를 사용하므로 연관관계를 관리하는 포인트는 2곳으로 늘어난다.

 

엔티티를 양방향 연관관계로 설정하면 객체의 참조는 둘인데 외래 키는 하나다. 그렇다면 둘 중 어떤 관계를 사용해서 외래키를 관리해야 하는지의 차이로 인해 외래키를 관리하는 객체를 연관관계의 주인이라고 한다.

 

연관관계의 주인만이 데이터베이스 연관관계와 매핑되고 외래키를 관리할 수 있다. 반면 주인이 아닌 쪽(mappedBy)는 읽기만 가능하다.

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

JPA - 프록시  (0) 2024.01.19
고급매핑 - 상속 관계 매핑  (0) 2024.01.15
엔티티 매핑(2) - 컬럼 매핑  (0) 2024.01.03
엔티티 매핑(1) - 엔티티, 기본 키 매핑  (1) 2023.12.29
영속성 관리(2)  (0) 2023.12.28