읽기 작업 : 두개의 엔티티를 읽을 때 두번의 JOIN 필요
각각의 엔티티와 중간 테이블을 조인한 후 중간 테이블 기준으로 다시 다른 엔티티와 조인하는 방식
쿼리 복잡도 증가, 쿼리 실행 시간이 길어짐
쓰기 작업 : 다대다 관계에서 새로운 관계를 추가하거나 삭제할때 중간테이블에 추가적인 insert, Delete 작업이 필요. 한 엔티티와 관련된 데이터를 삭제하면, 중간 테이블에서 해당 관계를 먼저 삭제한 후, 관련 엔티티에서 데이터를 삭제해야 합니다. 이로 인해 성능 저하
N+1 문제
Category가 여러 Book과 다대다 관계를 가지고 있다고 가정할 때, 하나의 Category를 조회할 때 Book 엔티티와의 다대다 관계를 지연 로딩으로 처리하면, 추가로 N개의 쿼리가 발생
하나의 카테고리에 대해 모든 책을 가져올 때, 카테고리당 하나의 쿼리와 관련된 모든 책에 대해 N개의 쿼리가 추가적으로 실행
중복된 데이터 문제
조인을 통해 데이터를 가져오는데, 결과적으로 동일한 엔티티 데이터가 여러 번 중복될 수 있습니다. 이는 메모리 사용량이 증가하게 되어 성능에 악영향
중간 테이블(Join Table)을 명시적으로 사용하는 방식으로 다대다 관계를 풀어냅니다. 이 방식에서는 다대다 관계를 풀어서 일대다(OneToMany)와 다대일(ManyToOne) 관계로 변환하여 처리
두 엔티티가 서로 여러개의 인스턴스를 참조할 수 있기 때문에 이를 구현하기 위해서는 중간 테이블이 필요
양쪽 엔티티의 외래 키 포함 -> 두 엔티티 간의 연결을 관리
중간 테이블을 중간 엔티티로 확장하여 메타데이터 관리 가능
추가적인 정보를 저장 할 수 있다.
추가적인 필드 저장:
예를 들어, 책이 특정 서브 카테고리에 추가된 날짜나 상태 정보를 중간 엔티티에 저장할 수 있습니다.
복잡한 비즈니스 로직 관리:
중간 엔티티를 통해 두 엔티티 간의 상태나 연관된 비즈니스 로직을 관리할 수 있습니다.
관계 속성 관리:
예를 들어, 두 엔티티 간의 관계가 활성/비활성화 상태인지, 또는 이 관계가 언제 형성되었는지와 같은 정보도 중간 엔티티에 저장할 수 있습니다.
장점: 성능을 최적화할 수 있으며, 중간 테이블에 추가적인 메타데이터(예: 생성 일자, 상태 정보)를 저장할 수 있습니다.
단점: 설계가 복잡해지고, 중간 엔티티를 직접 관리해야 하므로 구현 부담이 생길 수 있습니다
지연 로딩(Lazy Loading) 사용
다대다 관계에서 모든 데이터를 즉시 로딩하면 성능에 큰 영향을 미칠 수 있습니다. FetchType.LAZY를 사용하여 실제로 필요한 데이터만 로드
배치 쿼리 사용
다대다 관계에서 N+1 문제를 해결하기 위해 배치(fetch join) 쿼리를 사용할 수 있습니다. Hibernate는 JOIN FETCH를 사용하여 관련 엔티티를 한 번에 로드