본문 바로가기
JPA

JPA - 연관관계 매핑 기초(3) : 양방향 연관관계와 연관관계의 주인 (2)

by 왈레 2022. 4. 9.

1. 양방향 연관관계와 연관관계의 주인 (2) - 주의점, 정리

 

양방향 매핑시 가장 많이 하는 실수

연관관계의 주인에 값을 입력하지 않는다.

 

 

양방향 매핑시 연관관계의 주인에 값을 입력해야 한다.

 

 

양쪽에 값을 설정하지 않고 주인에만 값을 설정할 경우 발생하는 문제 2가지

1. 값이 정상적으로 출력되지 않는다.

 

연관관계의 주인에만 값을 입력하고 ex) member.setTeam(team);

바로 Team.getMembers()하고 for문을 돌려 member 값을 출력해보면 값이 출력되지 않는다.

 

왜냐하면 Team 객체는 현재 DB insert되지 않은 영속성 컨텍스트 1 캐시저장소에만 저장되있는 순수한 객체 상태이기 때문이다.

 

물론em.flush(), em.clear() 해준 상태로 team.getMembers()를하면 되지만,

처음부터 양쪽에 값을 설정해주는 객체지향적으로 생각해도 맞고 실수를 원천적으로 방지할 있다.

 

 

2. 테스트 케이스 작성할 문제가 된다.

 

단위테스트의 경우 JPA없이 순수하게 자바로 작성하기 때문에 1번처럼 값이 정상적으로 출력되지 않는다.

 

 

연관관계 편의 메서드

연관관계 편의 메서드는 양쪽에다 넣을 있는데 양쪽에다 넣으면 문제가 발생할 있으니 한쪽을 정해서 넣어야한다.

(연관관계의 주인은 member지만 값을 어디서 세팅하는지는 개발자의 자유이다. 상황에 따라 적절하게 정하면 된다.)

 

간단한 연관관계 편의 메서드 예제)

public class Member{
    // 실무에서는 Setter를 사용하지 않는다. 메서드에 의미를 부여해서 만든다.
    // ex)changeTeam()이라든지...
    public void setTeam(team team){ 
        this.team = team;
        team.getMembers().add(this); // 이렇게하면 실질적으로 연관관계의 주인에만 값을 설정해주면 된다.
    }
}​

실제로 연관관계 편의 메서드를 사용하려면 좀더 복잡하다.

간단한 예시를 들면 team안에 member가 나 자신이 있냐 없냐 null 체크해야하고 등등...

 

 

양방향 매핑시에 무한 루프를 조심하자.

toString(), lombok, JSON 생성 라이브러리는 양방향 매핑시 문제가 된다.

 

lombok @data 여러 보일러플레이트 함수를 만들어주는데 toString() 포함하고 있어 문제가 된다.

JSON 생성 라이브러리 같은 경우 Entity(양방향 연관관계) 컨트롤러에서 json으로 return해버릴 문제가된다.

객체를 JSON으로 응답 시 에러가 나는 원인은 객체의 모든 getter 함수가 호출되고 JSON으로 파싱하여 응답하기 때문

 

 

간단한 해결방법

  • @data사용 금지
  • @getter 사용
  • 컨트롤러에서 Entity 반환을 금지하고 ResponseDto를 따로 만들어서 그걸로 리턴
    (컨트롤러에서 데이터를 받을 때도 Entity로 바로 받지않고, requestDto를 따로 만들어서 그걸로 받아준다.)

 

※ 참고로 @JsonIgnoreProperties 사용해서 특정 필드를 제외할 방법이 있다.

특정 컬럼(참조용 객체) 위에 @JsonIgnoreProperties 달아주면 ex) @JsonIgnoreProperties({"user"})

"OO안에 User 무시하고 파싱하라" 라는 의미가 된다. (그 컬럼의 getter 호출 안함)

 

2. 연관관계 매핑하는법

테이블 구조

 

 

객체 구조

 

연관관계 매핑 설계 순서

  1. 테이블 구조를 보고(FK 외래키를 보고) 먼저 단방향 연관관계 매핑을 잘해준다.
  2. 추가적으로 개발시 양방향 연관관계가 필요하다 생각되면 그때 추가하자.

실전에서는 JPQL 많이 작성하게 되는데 이때 편리성을 위해 양방향 연관관계가 필요하다.

가능하면 최대한 단방향으로 해야하지만 실무에서는 양방향을 많이쓰게된다.

 

 

양방향 연관관계 추가시 의심해보기

양방향 연관관계가 필요할때 설계를 한번 의심해봐야한다.

관심사를 제대로 끊어내는 것도 중요하다.

member에서 order 가질필요가 없다.

member에서 orderlist 찾을게 아니라, order에서 member 찾는것이 바람직하다.

member orderList 가지고 있는것은 member 핵심을 벗어난다.

연습을 위한 예제일뿐, 실제론 안좋은 케이스이다.

 

반대로 Order orderitemList 가지는 것은 꽤 가치가 있다.

"무저건적인 관심사 분리", "무저건 양방향 연관관계를 좋지않다." 이게아니라 비즈니스적인 관점에서 상황에따라

좋은예, 나쁜예가 있다. 개발자가 적절히 판단하고 추가하면 된다.

 

※출처 - 인프런 김영한 JPA

댓글