시작하기 앞서 저의 글에대한 피드백이나 지적은 언제나 환영입니다 😊
용어를 먼저 이해해보자
"객체지향 설계의 목표는 자율적인 객체들의 협력 공동체를 만드는 것이다."
-조영호(객체지향의 사실과 오해)
: 객체를 테이블에 맞추어 데이터 중심으로 모델링하면, 협력관계를 만들 수 없다.
@ManyToOne
@OneToMany
@OneToOne
@ManyToMany
모두 대칭성이 있다.
@ManyToOne
@JoinColumn(name = "TEAM_ID)
단방향 -> Member에서 Team으로 접근 가능하지만 Team에서 Member로 접근 불가하다
하지만 참조(reference)를 넣어두면 양쪽 다 참조해서 접근할 수 있게된다.
양방향 연관관계를 만들어도 단방향과 비교해봐도 테이블에 변화가 없다 (테이블은 결국 다 Join으로 조회 할 수 있기때문이다) 테이블의 연관관계는 외래키 하나로 양방향이 다 있는것이다.
이때 객체에선 문제가 일어난다 Member에선 Team으로 갈 수 있지만 Team에선 Member에 접근 할 수 있는 방법이 없었다.(객체참조와 테이블의 외래키의 가장 큰 차이이다)
그래서 Team에 List형식의 memebers를 넣어주면 양쪽으로 다 접근할 수 있게된다.
mappedBy
속성을 사용하지 않는다.mappedBy
속성으로 주인을 지정해준다mappedBy = "team"
으로 team을 주인으로 지정하고 주인인 team이 외래키를 관리한다.
Member.team
이 연관관계의 주인 (진짜매핑) 이다.
Team.members
는 주인의 반대편(가짜매핑)
그렇지 않으면 단점이 있다
1. 일단 헷갈린다
2. Team.members의 값을 바꿨다고 가정해보자 그럴 시 다른 테이블에 update쿼리문이 나가게된다
(외래키관련으로 (Team에서 insert쿼리, Member에서 update쿼리 등이 나가고 복잡해져버린다.))
3. 위와 같은 이유들로 성능이슈 또한 날 수 있다.
이렇게 되면 설계가 깔끔해지며 외래키가 있는 테이블에서 관리가 된다는 장점이 있다.
즉 DB의 N쪽이 무조건 연관관계의 주인이 된다
ex)@ManyToOne
예를 들자면 자동차와 자동차의 바퀴가 있다.
비즈니스적으로 보면 자동차가 훨씬 중요하지만 연관관계의 주인을 바퀴로 잡는 격인 것이다.
정말 간단하게 말해서 연관관계의 주인은 그냥 N쪽 '다'인 쪽을 연관관계의 주인으로 설정하면 된다.
toString()
, lombok
, JSON생성 라이브러리
toString()
, lombok
: toString()
을 양쪽에서 출력하여 스택오버플로우 오류가 일어난다.JSON생성 라이브러리
: 쭉 다 뽑아버리기 때문에 엔티티를 JSON으로 바꾸는 순간 무한루프 -> 스택오버플로우(장애) 컨트롤러에서 엔티티를 바로 반환할때 엔티티를 json으로 변환하며 연관관계가 양방향으로 걸려있다면 그때 계속 서로 파고들면서 장애가 남오류해결
toString
: 써도 매핑된 것들을 빼고 써라json생성 라이브러리
: 컨트롤러에서 절대 엔티티를 반환하지마라 (DTO사용하기)사실 양방향 연관관계 매핑에는 정답이 있다.
바로 순수한 객체 관계를 고려하여 항상 양쪽 다 값을 넣어주는 것이다.
연관관계 편의 메서드 예시
//연관관계 주인인쪽(Member)에서 작성
public void changeTeam(Team team) {
this.team = team;
team.getMembers().add(this);
}
//연관관계 주인이 아닌쪽(Team)에서 작성
public void addMembers(Member member) {
member.setTeam(this);
members.add(member);
}
JPA에서 중요한 다른 한가지 연관관계 매핑에 대해 정리해보았습니다.
JPA설계 등 에서 매우 중요하다고 생각되었으며
다음 글은 다중성을 이용한 다양한 연관관계 매핑 입니다!
긴 글 읽어주셔서 감사합니다.😊