김영한 님의 "자바 ORM 표준 JPA 프로그래밍" 책을 정리한 포스팅 입니다.
1. 단방향 연관관계
객체 연관관계
- 참조로 연관관계를 맺음.
단방향 관계
- 한 객체가 다른 객체 참조 O (다른 객체가 반대 객체 참조 X)
- 객체 그래프 탐색을 통해 연관관계 파악 가능
테이블 연관관계
- 외래키로 연관관계를 맺습니다.
양방향 관계
- 한 객체가 다른 객체 참조 O + 다른 객체가 반대 객체 참조 O
- 연관관계인 모든 테이블이 조인 쿼리에 쓰임
연관 관계 매핑
@JoinColumn
- 외래키 설정 (조인 시 사용)
name | 외래키 이름 |
referencedColummnName | 외래키가 참조하는 컬럼명 |
foreignKey | 외래키 제약조건 (테이블 생성시에만) |
@ManyToOne
- 다대일 관계 매핑
optional | 관련 엔티티 존재 유무 | true |
fetch | 페치 전략 | @ManyToOne = FetchType.EAGER @OneToMany=FetchType.LAZY |
cascade | 영속성 전이 기능 사용 유무 | |
targetEntity | 관련 엔티티 타입 |
@Entity
public class Member {
@Id
@Column(name = "MEMBER_ID")
private String id;
//연관관계 매핑
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
//연관관계 설정
public void setTeam(Team team) {
this.team = team;
}
//Getter, Setter ...
}
@Entity
public class Team {
@Id
@Column(name = "TEAM_ID")
private String id;
//Getter, Setter ...
}
2. 연관관계 사용
저장
참조 객체와 함께 DB에 저장
- (슈퍼타입) 참조객체 저장
- (서브타입) 객체 저장
조회
객체 그래프 탐색
- 연관관계를 사용하여 조회
Member member = em.find(Member.class, "member1");
Team team = member.getTeam(); // 객체 그래프 탐색
JPQL
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();
수정
- em.update() 메서드 없음.
- 커밋할 때(flush()), 변경 감지 기능이 동작함.
제거
- 연관관계 객체 null로 셋팅
private static void deleteRelation(EntityManager em) {
Member member = em.find(Member.class, "member1");
member.setTeam(null);
}
3. 양방향 연관관계
- 테이블: 외래키 하나로 양방향 조회 가능
- 객체에서도 양방향 조회 설정 가능 (매핑)
양방향 연관관계 매핑
@OneToMany
- 일대다 관계
- 여러 건과 연관관계 설정 가능
- mappedBy
- (양방향 매핑일 때) 연관관계 주인 설정
- 반대쪽 매핑객체의 필드 이름
@Entity
public class Member {
@Id
@Column(name = "MEMBER_ID")
private String id;
//연관관계 매핑
@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>();
}
4. 연관관계 주인
테이블
- 외래키 하나로 두 테이블의 연관관계 관리
객체
- 양방향 연관관계 존재 X
- 단방향 연관관계 2개를 묶어 구현 (두 개의 참조 발생)
- 외래키를 관리할 주인 설정 필요 (연관관계 주인)
주인
- 외래키 지정 (연관관계 매핑)
- 외래키 관리 (설정, 변경)
주인 X
- 읽기만 가능
6. 양방향 연관관계 주의점
연관관계 맺기
주인에 연관관계 값 입력 X
- db에 null 값으로 저장됨
Member member = new Member(); // 주인
member.setName("Member1");
em.persist(member);
Team team = new Team();
team.setName("TeamA");
team.getMembers().add(member);
em.persist(team);
해결방안 1
- 필수) 주인으로부터 연관관계 설정
- 권장) 양쪽 모두에 값 셋팅 (순수한 객체 고려): 테스트 용이
Team team = new Team();
team.setName("TeamA");
em.persist(team);
Member member = new Member(); // 주인
member.setName("Member1");
member.setTeam(team);
em.persist(member);
team.getMembers().add(member);
해결방안 2
- 연관관계 편의 메소드 (주인)
- setter 함수를 정의하여 사용 (양쪽 모두에게 값이 입력되도록)
public class Member {
private Team team;
public void setTeam(Team team) {
this.team = team;
team.getMembers().add(this);
}
}
연관관계 변경
이전 연관관계의 객체가 영속 상태
- 연관관계만 변경 시, 수정 전의 연관관계 객체를 읽음
member1.setTeam(team1);
member1.setTeam(team2);
Member findMember = team1.getMembers().get(0); // 여전히 member1이 조회된다.
해결방안
- 연관관계를 변경할 경우, 반대 객체의 연관관계도 삭제 필요
public void setTeam(Team team) {
if (this.team != null) {
this.team.getMembers().remove(this);
}
this.team = team;
team.getMembers().add(this);
}
무한 루프
- 객체 간 상호 참조로 인해 발생할 수 있음
- toString(), equals(), hashCode()
- JSON Serializing
해결 방안 (toString())
- 순환 참조 피하기
public class Team {
private String name;
private List<Member> members = new ArrayList<>();
@Override
public String toString() {
return "Team{name='" + name + "'}"; // members 리스트 제외
}
}
public class Member {
private String name;
private Team team;
@Override
public String toString() {
return "Member{name='" + name + "'}"; // team 필드 제외
}
}
해결 방안 (JSON Serializing)
- @JsonManagedReference: 직렬화 시, 포함되는 필드 지정
- @JsonBackReference: 직렬화 시, 제외되는 필드 지정
public class Team {
private String name;
@JsonManagedReference
private List<Member> members = new ArrayList<>();
}
public class Member {
private String name;
@JsonBackReference
private Team team;
}
'Spring > Spring Data JPA' 카테고리의 다른 글
[자바 ORM 표준 JPA 프로그래밍] 7. 고급 매핑 (1) | 2023.12.28 |
---|---|
[자바 ORM 표준 JPA 프로그래밍] 6. 다양한 연관관계 매핑 (0) | 2023.12.27 |
[자바 ORM 표준 JPA 프로그래밍] 4. 엔티티 매핑 (1) | 2023.11.28 |
[자바 ORM 표준 JPA 프로그래밍] 3. 영속성 관리 (0) | 2023.11.28 |
[자바 ORM 표준 JPA 프로그래밍] 2. JPA 시작 (0) | 2023.11.28 |