객체를 양방향으로 참조할 경우 단방향 연관관계를 2개 만들어야 함 (A → B, A ← B)
테이블 연관관계 :
외래 키(FK)로 연관관계를 맺음, 조인(Join) 연산 사용
외래 키를 사용하는 테이블 연관관계는 양방향(A JOIN B 가능하면 B JOIN A 도 가능)
객체 관계 매핑
@Entity
public class Member {
...
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
...
}
@Entity
public class Team {
@Id
@Column(name = "TEAM_ID")
private String id;
...
}
@ManyToOne : 다대일(N:1) 관계 매핑 정보
fetch 속성 - FetchType.EAGER, FetchType.LAZY
cascade 속성 - 영속성 전이 기능
@JoinColumn(name="TEAM_ID") : 외래 키 매핑시 사용
생략시 외래 키를 찾을 때 기본 전략(필드명 + _ + 참조하는 테이블 컬럼명) 사용
연관관계 사용
저장
member1.setTeam(team1); → INSERT INTO MEMBER ( ... ) VALUES ( ... , ‘team1’)
team1 인스턴스의 id 값이 “team1” 임
조회
객체 그래프 탐색
Member member = em.find(Member.class, "member1");
Team team = member.getTeam(); // 객체 그래프 탐색
객체지향 쿼리 사용
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", "팀1")
.getResultList();
수정
Member member = em.find(Member.class, "member1");
member.setTeam(team2);
setter 사용 → 트랜잭션 커밋시 플러시 & DB 반영
삭제
Member member = em.find(Member.class, "member1");
member.setTeam(null);
member.setTeam(null); → UPDATE MEMBER SET TEAM_ID=null, ... WHERE ID=‘member1’
연관 엔티티 삭제시 기존 연관관계를 먼저 제거하고 삭제해야함
양방향 연관관계
@Entity
public class Member {
...
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
...
}
@Entity
public class Team {
@Id
@Column(name = "TEAM_ID")
private String id;
...
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<Member>();
...
}
mappedBy : 양방향 매핑시 사용, 반대쪽 매핑 필드 이름을 값으로 준다
연관관계의 주인
객체는 양방향 연관관계 가 아니라 단방향 연관관계(참조) 2개
반면 테이블에서 외래 키(FK)는 1개
JPA 에서는 외래 키(FK)를 가진 쪽을 연관관계 주인 으로 설정함으로써 이 차이를 메꾼다
연관관계의 주인만이 DB의 연관관계와 매핑되고 외래 키를 관리(등록, 수정, 삭제)함
주인이 아닌 쪽은 읽기만 할 수 있다
연관관계의 주인을 mappedBy 로 표현해준다
mappedBy = “team”
team 을 필드로 하는 Member 가 주인
주인은 mappedBy 사용x
양방향 연관관계 저장 & 주의점
주인이 아닌 방향은 값을 설정하지 않아도 DB에 외래 키 값이 정상 입력된다
하지만 객체 관점에서는 양쪽 방향에 모두 값을 입력해주지 않으면 기대하는 값이 나오지 않는다
따라서 객체의 관점을 고려하여 양방향 모두 값을 입력해 관계를 맺어줘야 한다(주인이 아닌 곳에도)
또한 객체의 관점때문에 연관관계를 변경할 때는 기존 연관관계를 삭제하는 코드를 추가해야 한다.
연관관계 편의 메소드
public void setTeam(Team team) {
if (this.team != null) {
this.team.getMembers().remove(this);
}
this.team = team;
team.getMembers().add(this);
}
목표
단방향 연관관계
객체 연관관계 vs 테이블 연관관계
객체 관계 매핑
@ManyToOne
: 다대일(N:1) 관계 매핑 정보FetchType.EAGER
,FetchType.LAZY
@JoinColumn(name="TEAM_ID")
: 외래 키 매핑시 사용필드명
+_
+참조하는 테이블 컬럼명
) 사용연관관계 사용
저장
member1.setTeam(team1);
→INSERT INTO MEMBER ( ... ) VALUES ( ... , ‘team1’)
조회
객체 그래프 탐색
객체지향 쿼리 사용
수정
삭제
member.setTeam(null);
→UPDATE MEMBER SET TEAM_ID=null, ... WHERE ID=‘member1’
양방향 연관관계
mappedBy
: 양방향 매핑시 사용, 반대쪽 매핑 필드 이름을 값으로 준다연관관계의 주인
mappedBy
로 표현해준다mappedBy = “team”
mappedBy
사용x양방향 연관관계 저장 & 주의점
연관관계 편의 메소드