2024. 1. 4. 23:36ㆍspring/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 |