목표 : 객체와 테이블 연관관계 차이 이해
객체의 참조와 테이블의 외래키를 매핑
방향: 단방향, 양방향
다중성: 1:1, 1:N, N:N, N:1 이해
연관관계 주인: 객체 양방향 연관관계는 관리 주인이 필요.
목차
연관관계가 필요한 이유
단방향 연관관계
양방향 연관관계와 연관관계주인
실전예제 2. 연관관계 매핑 시작.
- 연관관계가 없는 경우.
테이블에 맞추어 객체를 모델링하면 협력관계 만들수없다.
테이블은 외래키로 join해서 연관된 테이블 찾는다.
객체는 참조를 통해 연관된 객체 찾는다.
이런 차이떄문에 불편!
그래서 설계할떄 단방향 연관관계로 설계해야해.
Member findMember = em.find(Member.class, member.getId());
Team findTeam = findMember.getTeam(); // member -> Team 접근가능.
System.out.println("findTeam = " + findTeam.getName());
양방향 연관관계와 연관관계 주인
MappedBy
객체와 테이블간에 연관관계를 맺는 차이를 이해!!!
객체 양방향 연관관계 2개
객체는 단방향이 두개 있는거다.
회원 -> 팀 1개
팀 -> 회원 1개
ex)
class A {
B b;
}
class B {
A a;
}
A -> B (a.getB());
B -> A (b.getA());
테이블 양방향 연관관계 1개
회원 <->팀의 연관관계 1개
테이블은 외래키 하나로 두 테이블연관관계 관리! (Join 통해서)
여기서 문제가 되는게 다음그림과같다.
Member안에 team을 바꾸면 DB에 MEMBER를 업데이트 해줘야하나? 아니면 Team에 members를 바꿔야 업데이트 해줘야하냐?
그래서 둘중 하나는 외래키로 관리해야하고 이를위해 연관관계의 주인이라는 개념이 나옴.
연관관계 주인
객체의 두관계중 하나를 연관관계 주인으로 지정
이는 외래키를 등록 수정 하며 관리한다.
주인이 아닌쪽은 읽기만 가능.
MappedBy는 ~에 의해 매핑이 되었다는 의미이므로
주인(Member)은 Db에 등록,수정 가능 mappedBy속성 사용 X
주인 아닌쪽(Team)은 읽기만 되고 mappedBy 속성 사용 0
주인을 결정하려면?
테이블 에서 외래키가 있는곳을 객체에서 주인으로 두어라!
위에 그림을 보면 DB에 Team_Id가 Member에 있으므로 Member를 주인으로 정하자! 그래야 헷갈리지 않는다.
양방향 매핑할떄 주의할점
주의점 1 . 연관관계 주인이아닌 것에 값을 넣을떄
// 실수하는 부분
Member member1 = new Member();
member1.setUsername("member1");
em.persist(member1);
Team team1 = new Team();
team1.setName("TeamA");
team1.getMembers().add(member1); // 연관관계 주인아닌(Team)을 통해 변경사항 넣어줌.
em.persist(team1);
// 올바르게 수정
Team team2 = new Team();
team2.setName("TeamA");
em.persist(team2);
Member member2 = new Member();
member2.setUsername("member1");
member2.setTeam(team2); // 연관관계 주인(member)를 통해 Team 변경사항 넣어줌.
em.persist(member2);
// 이처럼 다음 라인을 추가해서 양방향에 값을 넣어주어 Team_id가 null인경우는 안나옴.
team2.getMembers().add(member2)
위에 좌측을보면 Team_ID가 비어있다.
이러한 실수를 막기위해 양방향에 값을 넣어주는게 안전하다.
위처럼 add해서 추가해줄수도있지만
가장 권장하는것은 메서드를 하나 만들어서 다음과같이 하는것이 좋다.
- Member 든 Team이든 둘중 한곳에서만 메서드만들면 된다.
public class Member {
private Team team;
public void chageTeam(Team team) { // Member기준으로 양방향으로 값을 넣어줌.
this.team = team;
team.getMembers().add(this)
}
}
public class Team {
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
public void addMember(Member member) { // Team기준으로 양방향으로 값을 넣어줌.
member.setTeam(this);
members.add(member);
}
}
주의점2. 양방향 매핑시 양방향 호출로인한 무한루프 조심
ex) toString(), lombok, json 생성 라이브러리
양방향 매핑 팁!!
- 처음엔 단방향 매핑만으로 설계를 하자!( 단방향만 잘해두면 나중에 반대방향 조회기능만 추가된거 -> 테이블에 영향 X)
- 양방향 매핑은 반대방향으로 조회기능이 추가가 된것뿐.
- 실무에서는 JPQL에서 역방향으로 탐색할 일이 많음. 그러다보니 양방향이 필요!
- 연관관계 주인은 외래키의 위치를 기준으로 정하자!
'𝗦𝗣𝗥𝗜𝗡𝗚 > 𝐎𝗥𝗠-𝗝𝗣𝐀' 카테고리의 다른 글
고급 매핑 (1) | 2024.01.03 |
---|---|
다양한 연관관계 매핑 (0) | 2024.01.03 |
엔티티 매핑 (0) | 2024.01.02 |
JPA 영속성 컨텍스트 (0) | 2023.12.27 |
JPA 구동방식 (0) | 2023.12.27 |