일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- Remember-me
- form login
- orphanRemovel
- 세션 고정 보호
- 세션 생성 정책
- Spring Security
- 동시 세션 제어
- @MappedSuperclasss
- 다대다
- JPQL
- ddl-auto
- 상속관계 매핑
- 기본값 타입
- 지연 로딩
- field column mapping
- 값 타입 비교
- 객제지향 쿼리 언어
- Database
- 임베디드 타입
- SessionManagementFilter
- AnonymousAuthenticationFilter
- jpa
- 값 타입 컬렉션
- 기본 키 매핑
- concurrentsessionfilter
- MySQL
- 즉시 로딩
- TABLE
- 양방향 매핑
- spring jpa
- Today
- Total
hoondev
[Spring JPA] 양방향 연관관계 본문
양방향 연관관계
테이블은 외래키하나로 양쪽 모두를 조회할 수 있으므로 따로 설정을 하지 않아도 양방향 연관관계이다.
하지만 객체는 양방향 연관관계 설정을 따로 해주어야 한다.
Member
@Entity
public class Member {
@Id @GeneratedValue
private Long id;
@Column(name = "USERNAME")
private String name;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
…
}
Team
@Entity
public class Team {
@Id @GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "team")
List<Member> members = new ArrayList<Member>();
…
}
단방향 연관관계일때의 팀과 비교해보면 members란 필드를 가진 것을 알 수 있다.
팀의 입장에서는 일대다 이므로 @OneToMany 어노테이션을 추가해준다.
mappedBy는 member에 있는 team변수와 매핑하겠다는 뜻이다.
양방향 매핑 저장, 조회
//객체 생성
Member member = new Member();
Team team = new Team();
//연관관계 설정
member.setTeam(team);
team.getMembers().add(member);
em.persist(member);
em.persist(team);
//조회
Member findMemberA = em.find(Member.class, member.getId());
Team findTeamA = em.find(Team.class, team.getId());
Team findTeamB = findMember.getTeam();
List<Member> members = findTeamA.getMembers(); //역방향 조회
양방향 연관관계 일때는 두개의 객체 모두 연관관계 설정을 해줘야 한다.
객체와 테이블이 관계를 맺는 차이
객체와 테이블의 연관관계는 차이가 있다.
객체
객체 연관관계 = 2개 • 회원 -> 팀 연관관계 1개(단방향)
팀 -> 회원 연관관계 1개(단방향)
테이블
테이블 연관관계 = 1개 • 회원 <-> 팀의 연관관계 1개(양방향)
객체는 사실 양방향이라고 하지만 풀어보면 서로 단방향 의존관계이다.
이런 이유 때문에 객체를 양방향으로 참조하려면 단방향 의존관계를 2개 만들어야 한다.
하지만 테이블은 외래키 하나로 두 테이블의 연관관계를 관리한다.
SELECT *
FROM MEMBER M
JOIN TEAM T ON M.TEAM_ID = T.TEAM_ID
SELECT *
FROM TEAM T
JOIN MEMBER M ON T.TEAM_ID = M.TEAM_ID
테이블과 달리 객체는 두 객체가 서로를 참조한다.
참조는 둘인데 외래키는 하나이기 때문에 여기서 차이가 발생한다.
이러한 차이로 외래키를 한쪽에서 관리해야하는데 관리하는 쪽이 바로 연관관계의 주인이다. 연관관계의 주인은 등록, 수정이 가능한 반면에 아닌쪽은 읽기만 가능하다. 주인이 아닌쪽이 바로 mappedBy 속성을 사용하는 것이다. mappedBy가 매핑되었다는 뜻이기 때문에 주인에 의해서 매핑 되었다는 뜻으로 이해하면 될 것이다.
그럼 두 객체중 어느 객체를 연관관계 주인으로 설정할까? 바로 외래키가 있는 쪽을 주인으로 설정하면 된다.
양방향 매핑 주의사항
양방향 매핑시 연관관계의 주인에 값을 입력해야 한다.
Team team = new Team();
team.setName("TeamA");
em.persist(team);
Member member = new Member();
member.setName("member1");
//역방향(주인이 아닌 방향)만 연관관계 설정
team.getMembers().add(member);
em.persist(member);
위의 코드처럼 실수하면 안된다.
Team team = new Team();
team.setName("TeamA");
em.persist(team);
Member member = new Member();
member.setName("member1");
team.getMembers().add(member);
//연관관계의 주인에 값 설정
member.setTeam(team); //**
em.persist(member);
이렇게 두 객체모두 값을 설정해줘야 한다. 하지만 사람이라면 실수할때가 있다.
이를 방지하기 위해 연관관계 편의 메서드를 작성하자.
연관관계 편의 메서드
public void setTeam(Team team) {
this.team = team;
team.getMembers().add(this);
}
무한 루프를 조심하자
lombok의 toString()같은 어노테이션 사용시 주의 해야 한다. 만약 member의 toString()을 호출하면 team의 toString()도 호출하게 되고 team은 members 필드를 가지고 있으므로 toString()을 호출하게 되고 ... 이러면 스택 오버 플로우가 발생하게 된다.
Reference
'Spring JPA' 카테고리의 다른 글
[Spring JPA] 일대다 관계 (0) | 2023.01.27 |
---|---|
[Spring JPA] 다대일 관계 (0) | 2023.01.26 |
[Spring JPA] 단방향 연관관계 (0) | 2023.01.23 |
[Spring JPA] 기본 키 매핑 (0) | 2023.01.22 |
[Spring JPA] 필드와 컬럼 매핑 (0) | 2023.01.21 |