일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- MySQL
- 자바
- 스프링 이메일 전송
- github 복제
- 프로그래머스
- 우분투
- JDBC
- 스프링부트 OpenAI API
- 비밀번호 재설정 API
- 저장소 이전
- swap 메모리
- 페이징 정렬
- Servlet
- JPQL
- Json 객체
- Git
- 값 타입
- MVC
- jar빌드
- 서버 배포
- git 충돌 해결
- springboot
- 넘파이
- JPA
- api 개발
- 저장소 복제
- HttpServletResponse
- 두수의 합 자바
- Chat GPT
- 파이썬
- Today
- Total
현의 개발 블로그
[연관관계 매핑] 양방향 연관관계 본문
객체 연관관계와 테이블 연관관계의 차이
테이블 연관관계는 1개로 방향 개념이 없다.
테이블은 외래키 하나로 두 테이블의 연관관계를 관리한다.
외래키 Member.TEAM_ID로 Member, Team 양쪽을 조인할 수 있다.
객체는 연관관계가 2개이다.
객체를 양방향으로 참조하려면, 단방향 연관관계 2개를 만들어야 한다.
Member와 Team 객체에 각각 참조값을 넣어 양쪽으로 참조를 할 수 있다.
양방향 매핑 규칙
두 개의 참조값 중 하나로 외래키를 관리해야 한다.
Member.team이 바뀌었을 때 TEAM_ID를 바꿔야 할지,
Team.Members 가 바뀌었을 때 TEAM_ID를 바꿔야 할지 정해야 한다.
두 객체의 관계 중 하나를 연관관계의 주인으로 지정한다.
연관관계의 주인만이 외래키를 수정할 수 있다.
연관관계 주인이 아닌 쪽은 외래키를 읽기만 할 수 있다.
주인이 아닌 쪽에 mappedBy 속성으로 주인을 지정한다.
외래키가 있는 곳을 연관관계의 주인으로 정한다.
외래키는 1 : N 중 N에 위치하므로, 여기서는 Member.team이 연관관계의 주인이다.
양방향 매핑
Member에서 Team을 참조하기 위해 Member.team을 추가한다.
@JoinColumn을 사용해 테이블의 TEAM_ID와 매핑해 준다.
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
Team에서 Member를 참조하기 위해 Team.members를 추가한다.
연관관계 주인이 아니기 때문에 mappedBy 옵션으로 주인을 지정한다.
@OneToMany(mappedBy = "team") //Member의 team과 매핑됨
private List<Member> members = new ArrayList<>();
양방향 매핑을 통해 양방향 객체 그래프 탐색이 가능해졌다.
// Team에서 Member 조회
Team findTeam = em.find(Team.class, team.getId());
int memberSize = findTeam.getMembers().size();
// Member에서 Team 조회
Member findMember = em.find(Member.class, member.getId());
List<Member> members = findMember.getTeam().getMembers();
양방향 매핑 주의점
양방향 세팅 시 양쪽에 다 값을 입력해야 한다.
연관관계 주인의 반대편에 값을 입력한 예제이다.
연관관계 주인에 값을 입력하지 않아서 외래키 값이 null이다.
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);
연관관계 주인에는 반드시 참조값을 대입해야 한다.
순수한 객체 관계를 고려해 객체 양쪽에 값을 입력하는 게 좋다.
연관관계 편의 메서드를 작성하자
양쪽에 연관관계를 주입하는 메서드를 작성하면 데이터가 누락될 위험이 없어진다.
아래는 Member에 연관관계 편의 메서드를 작성한 예시이다.
public void changeTeam(Team team){
this.team = team;
team.getMembers().add(this);
}
반대로 Team에 Member를 주입하는 연관관계 편의 메서드를 작성할 수도 있다.
두 객체 1과 N 중 어느 쪽에 작성할지는 상황에 따라 결정하면 된다.
public void addMember(Member member){
member.setTeam(this);
members.add(member);
}
양방향 매핑 시에 무한 루프를 조심하자
양방향 연관관계가 있는 객체 모두에 toString()을 넣으면 무한 루프에 빠진다.
toString 뿐만 아니라 Json 생성 라이브러리를 사용할 때도 무한 루프가 발생한다.
Controller에서 양방향 연관관계를 가진 엔티티를 직접 반환한다면,
값을 Json으로 변경 시 두 엔티티가 묶여서 무한 루프가 일어난다.
따라서 엔티티를 직접 반환하지 말고 DTO로 변환 후 반환하자.
양방향 매핑 정리
단방향 매핑만으로 연관관계 매핑은 완료된 것이다.
양방향 매핑은 반대 방향으로 조회(객체 그래프 탐색) 기능이 추가된 것뿐이다.
객체 입장에서 양방향 매핑은 고려할 사항이 많아진다.
기본적으로 단방향 매핑으로 설계하고, 역방향으로 객체 탐색이 꼭 필요할 때 양방향 매핑을 하자.
양방향 매핑을 추가해도 테이블에는 영향을 주지 않는다.
연관관계 주인은 외래 키의 위치를 기준으로 정하자.
Reference
자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의
JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., - 강의 소개 | 인프런
www.inflearn.com
'스프링부트 이론 > JPA' 카테고리의 다른 글
[다양한 연관관계 매핑] 다대일 (0) | 2023.05.23 |
---|---|
[연관관계 매핑] 실전 예제 (0) | 2023.05.13 |
[연관관계 매핑 기초] 연관관계 필요성, 단방향 연관관계 (0) | 2023.05.11 |
[엔티티 매핑] 실전 예제 (0) | 2023.05.11 |
[엔티티 매핑] 기본 키 매핑 (0) | 2023.05.10 |