양방향으로 매핑을 해도 테이블 연관 관계는 변한 것이 없다.
테이블은 member에서 team을, team에서 member를 외래키 하나로 join 해서 자유롭게 조회할 수 있다.
하지만 객체는 team에 List<Member> members
를 추가해야 접근이 가능하다.
양방향 관계에서 N(다)에 해당하는 Member엔티티의 team필드는 @ManytoOne
어노테이션을 추가한다.
@Entity
public class Member {
@Id
@GeneratedValue
@Column(name="MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String name;
private int age;
@ManyToOne
@Column(name = "TEAM_ID")
private Team team;
}
양방향 관계에서 1(일)에 해당하는 Team엔티티의 List<Member> members
필드는
@OneToMany(mappedBy = "team")
어노테이션을 추가한다.
@Entity
public class Team {
@Id
@GeneratedValue
@Column(name="TEAM_ID")
private Long id;
private String name;
// Member 엔티티에 있는 'team' 필드가 연결되어 있다는 의미
@OneToMany(mappedBy = "team")
List<Member> members = new ArrayList<>();
// 리스트는 초기화 하는 것이 관례다.
// add 할 때 NullPointException를 방지한다.
}
Team엔티티에서 member엔티티를 조회할 수 있다.
public class JpaMain() {
public static void main(String[] args) {
...
Team findTeam = em.find(Team.class, team.getId());
// 이제 team에서도 member를 조회할 수 있다.
// 역방향 조회 가능
int memberSize = findTeam.getMembers().size();
}
}
객체는 연관 관계가 2개다.
테이블은 연관 관계가 1개다.
member를 새로운 team에 넣고 싶은데 member에서 team 값을 바꿔야할지 team에서 members 값을 바꿔야할지 딜레마가 온다.
DB 입장에서는 member에 있는 FK인 team_id만 업데이트 되면 된다.
결국 member, team 중 하나만 외래키를 관리해야 한다.
연관 관계의 주인을 정해야 하는 것이다.
객체의 두 관계중 하나를 연관관계의 주인으로 지정
연관관계의 주인만이 외래 키를 관리(등록, 수정)
주인이 아닌쪽은 읽기만 가능
주인은 amppedBy 속성사용 X
주인이 아니면 amppedBy 속성으로 주인 지정
만약 Member.team이 주인이 된다면
외래키가 Member 엔티티에 존재하기 때문에, Member엔티티에 변경사항이 있을 때 MEMBER 테이블에 업데이트 쿼리가 나갈 것이다.
하지만 Team.members가 주인이 된다면
외래키가 Team 엔티티에 존재하기 때문에, Member엔티티의 변경사항이 있을 때 내가 수정한
TEAM 테이블이 아닌 MEMBER 테이블에 업데이트 쿼리가 나갈 것이다.
-> Team 엔티티를 수정했는데, MEMBER 테이블에 쿼리가 나가기 때문에 혼란스러울 수 있다.
@ManyToOne
참고 :
김영한. 『자바 ORM 표준 JPA 프로그래밍』. 에이콘, 2015.