오늘은 양방향 @ManyToMany 연관관계를 효과적으로 구성하는 방법에 대해 알아보았다.
먼저 양방향 @ManyToMany 연관관계는 양쪽으로부터 탐색할 수 있으므로 양쪽 모두 부모가 된다. 둘 다 부모이기 때문에 둘 중 누구도 외래 키를 보유하지 않고 연결 또는 조인 테이블로 알려진 별도의 테이블에 저장되는 2개의 외래 키를 갖는다. 이 연결 테이블은 숨겨져 있으며 자식 측 역할을 한다.
그럼 @ManyToMany 연관관계를 어떻게 하면 효과적으로 사용할 수 있을까?
1. 항상 List가 아닌 Set을 사용
@ManyToMany의 대부분의 상황에서 List보다 Set의 성능이 뛰어나다. 특히 삭제 처리와 관련해 Set을 사용하고 List는 피하는 것이 좋다고 한다.
2. 연관관계의 양측 동기화 상태 유지
addBook(), removeBook(), removeBooks() 같이 양측의 동기화를 하는 기능을 가진 도우미 메서드를 조금 더 많이 사용하는 곳에 작성하자. 예를 들어 비즈니스 로직이 도서보다 저자를 더 많이 다룬다면 author에 도우미 메서드를 만들자.
3. CascadeType.All 및 CascadeType.REMOVE 사용하지 않기
대부분의 경우 제거에 대한 전이는 좋은 생각이 아니다. 예를 들어 Author 엔티티를 삭제해도 다른 저자에 의해 Book이 참조될 수 있기 때문에 Book 제거가 호출되지 않아야 한다. 따라서 CascadeType.All과 CascadeType.REMOVE를 피하고 명시적으로 CascadeType.PERSIST와 CascadeType.Merge를 사용하자.
4. 조인 테이블 설정
조인 테이블명과 컬럼명을 명시적으로 설정하면 개발자가 혼동 벗이 정보를 참조할 수 있다.
@JoinTable(name = "author_book",
joinColums = @JoinColumn(name = "author_id"),
inverseJoinColumns = @JoinColumn(name = "book_id")
)
5. 연관관계 양측에서 지연 로딩 사용
기본적으로 @ManyToMany 연관관계는 지연 처리를 사용하자. fetchType.EAGER 사용 x
6. eqauls() 및 hashCode() 오버라이딩
equals()와 hashCode() 메서드를 적절하게 재정의함으로써 애플리케이션은 모든 엔티티 상태 전환에서 동일한 결과를 얻는다. 그리고 양방향 @ManyToMany 연관관계의 이 두 메서드는 양쪽에서 재정의돼야 한다.
7. toString() 오버라이딩 방법에 주의
지연 속성 또는 연관관계를 포함하는 toString()을 만들면 해당 데이터를 가져오는 별도의 sql 문이 실행되니 조심하자.
+ @ManyToMany는 간단한 관계를 표현할 때는 유용할 수 있지만, 실무에서는 대부분의 경우 확장성과 유연성, 성능 측면에서 한계가 있기 때문에 권장되지는 않는다. 중간 테이블에 추가적인 정보나 기능이 필요하다면 따로 엔티티를 만들어서 일대다 다대일로 매핑하자.
'Spring-Boot' 카테고리의 다른 글
redis로 채팅 메시지 다룰 때 이스케이프 조심해야 되는 이유 (1) | 2024.09.08 |
---|---|
스프링부트 filter에서 발생한 예외를 핸들링 해보자 (1) | 2024.08.30 |
토비의 스프링 3.1 Vol.1 750p ~ 850p 정리 (완료) (2) | 2024.01.05 |
토비의 스프링 3.1 Vol.1 650p ~ 750p 정리 (2) | 2024.01.04 |
토비의 스프링 3.1 Vol.1 550p ~ 650p 정리 (0) | 2024.01.02 |