✅ 단방향 연관관계 ✅ 양방향 연관관계 ✅ 연관관계의 주인
객체를 테이블에 맞추어 데이터 중심으로 모델링하면 아래와 같이 테이블과 객체 사이에는 이런 큰 간격이 생긴다.
즉, 협력 관계를 만들 수 없다.
따라서 객체의 참조와 테이블의 외래 키를 매핑해야 한다.
@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;
}
멤버와 팀이 다대일로 매핑되어야 하므로
@Entity
public class Team {
@Id
@GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
@OneToMany(mappedBy = "team")
List<Member> members = new ArrayList<Member>();
}
객체는 양방향으로 바꿨지만 테이블의 연관관계는 그대로인 것을 알 수 있다.
왜냐하면 FK를 사용한 JOIN을 통해 양쪽에서 불러올 수 있기 때문이다.
Member의 team으로 테이블 TEAM_ID(FK)를 매핑하거나
Team의 members로 테이블 TEAM_ID(FK)를 매핑하여
둘 중 하나로 외래키를 관리해야 한다.
그래서 나온 개념이 연관관계의 주인
양방향 매핑 규칙
- 객체의 두 관계중 하나를 연관관계의 주인으로 지정
- 연관관계의 주인만이 외래 키를 관리(등록, 수정) 주인이 아닌쪽은 읽기만 가능
- 주인이 아니면 mappedBy 속성으로 주인 지정
- 주인이 아닌쪽이 mappedBy 속성 사용X
테이블 상으로 외래 키가 있는 곳이 주인이 된다.
여기서는 Member에 외래키가 있기 때문에 Member.team이 연관관계의 주인
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
// 팀 저장
Team team = new Team();
team.setName("TeamA");
em.persist(team);
// 회원 저장
Member member = new Member();
member.setUsername("member1");
team.getMembers().add(member);
member.setTeam(team); // 🔥 연관관계의 주인에 값 설정 🔥
em.persist(member);
em.flush();
em.clear();
Member findMember = em.find(Member.class, member.getId());
List<Member> members = findMember.getTeam().getMembers();
for(Member m : members){
System.out.println("m = " + m.getUsername());
}
tx.commit();
} catch (Exception e){
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
👉 순수한 객체 관계를 고려하면 항상 양쪽 다 값을 입력해야 한다.
1. team.getMembers().add(member)
2. member.setTeam(team) : 연관관계의 주인에 값 설정
Member.class
public void setTeam(Team team) {
this.team = team;
team.getMembers().add(this);
}
- JPA 설계에서는 단방향 매핑만으로도 이미 연관관계 매핑은 완료된 것이므로 양방향은 잘 사용하지 않는 것이 좋음
- 양방향 매핑은 반대 방향으로 조회(객체 그래프 탐색) 기능이 필요할 때 (JPQL에서 사용) 추가하는 것이 좋음