
- 기존 Member -> Team 방향으로만 연결된 관계에서, 양방향으로 변경했다.
- 데이터베이스는 기존에도 외래키를 바탕으로 양방향으로 조회할 수 있으므로, 변경된 점이 없다.
@Entitypublic class Team {
...
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<Member>();
...
}
- 기존의 Team 엔티티에서 member 와의 연관을 가지는 collection 객체를 추가하고, @OneToMany 를 통해 연결할 수 있다.
- mappedBy 는 양방향 매핑일 때 사용하는데, 반대쪽 매핑의 필드 이름 값을 주면 된다.
- 위의 방식으로 설정하면, 팀을 조회하였을 때 해당 팀에 속한 멤버들이 collection 객체안에 모두 존재하게 된다.
- Lazy 방식이기 때문에, 해당 객체를 사용 (조회 등)할 때 해당 객체를 조회하는 select 쿼리가 전송되고 셋팅된다.
Team team = em.find(Team.class, 1);
List<Member> members = team.getMember();
// 해당 팀의 id 를 외래키로 가지는 모든 멤버가 getMember() 를 통해 조회할 수 있다
....
Member member = em.find(Member.class, 1);
member.setTeam(team);
em.persist(member);
// 찾은 영속화된 member 객체에 team 연관관계를 추가 및 해당 외래키를 저장할 수 있다.
양방향 연관관계의 주의점
- 연관관계의 주인에는 값을 입력하지 않고, 주인이 아닌 곳에만 값을 입력하는 경우가 많다.
Member member1 = em.find(Member.class, 1);
Member member2 = em.find(Member.class, 2);
// 두개의 데이터의 team 이 1이 아닌 경우로 가정한다.
Team team = em.find(Team.class, 1);
team.addMember(member1);
team.addMember(member2);
em.persist(team);
// 데이터베이스에 조회시, member1,2 의 team 연관관계 정보가 team (id 가 1) 으로 설정되지 않는다.
// 연관관계의 주인이 아닌 team 에만 데이터를 추가했기 때문에, 데이터베이스에 값이 반영되지 않는다.
// 즉, member1,2 에도 team 을 셋팅하고 persist 를 해야 한다.
- 연관관계의 주인이 아닌 곳에 데이터를 입력하지 않는 경우
Member member1 = em.find(Member.class, 1);
Member member2 = em.find(Member.class, 2);
Team team = em.find(Team.class, 1);
member1.setTeam(team);
member2.setTeam(team);
em.persist(member1);
em.persist(member1);
// 데이터베이스로만 봤을 경우에는 데이터가 잘 저장되므로 괜찮을 수는 있다.
// 하지만 객체의 입장으로는, team 에 member1,2 가 추가되었으며 member1,2 는 팀에대한 정보를 알고있어서
// 객체 그래프 탐색을 member -> team 은 가능하지만, team 에서 member 들의 정보는 없으므로 불가능하다.
// 즉, 양쪽 모두 설정하는게 좋다.
team.addMember(member1);
team.addMember(member2);
// 연관관계의 주인이 아니므로 저장시에는 사용되지 않지만, 객체의 입장으로는 해당 정보가 있는게 좋다....
양방향 연관관계를 저장하는 메소드
- 연관관계의 주인의 객체에 연관관계가 변경되는 메소드에 설정할 경우
class Member {
...
private Team team;
...
public void setTeam(Team team) {
if (this.team != null) this.team.removeMember(this);
// 해당되는 팀의 멤버가 변경되므로, 기존에 있었던 팀에서 해당되는 객체의 데이터를 제거해줘야 한다.
// 위 과정이 없더라도 데이터베이스 반영에는 문제가 없다. 하지만, 위에서 본것처럼 객체의 관점에서
// 기존에 영속화된 team 에는 반영이 안되므로, 객체의 입장에서 문제가 발생한다.
this.team = team;
team.addMember(this);
}
// 위와 같이 한번에 양방향 관계를 설정하는 메소드를 연관관계 편의 메소드라고 한다.
}