자바 ORM 표준 JPA 프로그래밍 - 김영한
책 내용을 정리한 내용입니다.
챕터5 - 연관관계 매핑 기초
5.1 단방향 연관관계
5.2 연관관계 사용
객체는 참조를 사용해서 관계를 맺고, 테이블은 외래키 를 사용해서 관계를 맺는다.
이런 차이점이 객체 연관관계와 테이블 연관관계 매핑에 어려움을 준다.
따라서 객체의 참조 - 테이블의 외래키를 매핑하는 방법을 목표한다.
방향
[단방향, 양방향] 이 있다. 회원과 팀이 관계가 있을 때
회원 -> 팀 또는 팀 -> 회원 둘 중 한쪽만 참조하는 것을 단방향 관계라 하고
회원 < - > 팀 양 쪽 모두 참조하는 것을 양방향 관계라고 한다.
"방향" 이라는 객체관계에만 존재하고 테이블 관계는 항상 양방향 이다.
다중성
[다대일, 일대다, 일대일, 다대다] 다중성이 있다.
회원과 팀이 관계가 있을 때 여러 회원이 한 팀에 속하므로 회원과 팀은 다대일 관계다.
반대로 한 팀에 여러 회원이 속할 수 있으므로 팀과 회원은 일대다 관계다
연관관계의 주인
객체를 양방향 연관관계로 만들면 연관관계의 주인을 정해야 한다.
class Member {
private String id;
private Team team;
private String userName;
}
class Team {
private String id;
private String name;
}
Member 객체는 Member.team 을 통해 Team 객체와 연관관계를 맺는다.
Member 에서 Team 을 조회할 수 있지만 Team 에서 Member 는 조회할 수 있다 (단방향 관계)
회원 테이블의 TEAM_ID 를 통해 팀-회원의 연관관계를 맺는다.
TEAM 도 TEAM_ID 를 통해 팀에 속한 회원을 조회할 수 있고
MEMBER 도 TEAM_ID 를 통해 회원이 속한 팀을 조회할 수 있다.
객체는 항상 단방향 연관관계이다.
만약 양방향을 만들고 싶다면 서로가 서로를 참조하도록 2개의 단방향 연관관계를 만들어 주어야 한다.
테이블은 항상 양방향 연관관계이다.
@Entity
public class Member {
@Id
private Long id;
private String userName;
@ManyToOne
private Team team;
}
@Entity
public class Team {
@Id
private Long id;
private String name;
}
JPA 를 사용하여 엔티트를 설계하면 아래와 같은 테이블 구조를 만들게 된다.
@Service
public class TestSave {
@PersistenceContext
private EntityManager em;
@Transactional
public void save(){
Team team1 = new Team(1l, "team1");
em.persist(team1);
Member member1 = new Member(1l, "user1");
member1.setTeam(team1);
em.persist(member1);
Member member2 = new Member(2l, "user2");
member2.setTeam(team1);
em.persist(member2);
}
}
@Transactional
public void find() {
Member member1 = em.find(Member.class, 1l);
Team team = member1.getTeam();
System.out.println(team.getName());
}
@Transactional
public void find2() {
String jpql = "SELECT m FROM Member m JOIN m.team t where t.name =:teamName";
List<Member> resultList = em.createQuery(jpql, Member.class)
.setParameter("teamName", "team1")
.getResultList();
for (Member member : resultList) {
System.out.println(member.getUserName());
}
@Transactional
public void update() {
Team team2 = new Team(2l, "team2");
em.persist(team2);
Member member1 = em.find(Member.class, 1l);
member1.setTeam(team2);
}
@Transactional
public void delete() {
Member member1 = em.find(Member.class, 1l);
member1.setTeam(null);
}
@Transactional
public void remove() {
member1.setTeam(null);
member2.setTeam(null);
em.remove(team);
}