25/1/
다 대 다(N:M)인 관계에서는 관계매핑을 어떻게 사용할까?
1:N관계에서 사용하는 어노테이션을 사용할 수 있다.
하지만 이런 관계는 주로 사용하지 않는다고 한다.
❗️클래스를 하나 더 만들어 1:N 관계로 만들어준다.
즉, 브랜드와 카테고리는 다대다 관계이기 때문에, 연결해주는 클래스를 하나 더 만들어준다.
package brandkon.brand;
import brandkon.category.Category;
import jakarta.persistence.*;
@Entity
public class BrandCategory {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
private Brand brand;
@ManyToOne
private Category category;
}
1) 구성 형태
브랜드 | 브랜드카테고리 | 카테고리
1 : N : 1
2) 필드
필드는 딱 연결되어 있는 데이터만 들어가 있다.
brand, category를 서로 1:N관계로만 설정되어 있는 부분을 brandCategory로 수정해준다.
//기존
@ManyToOne
private Category category;
//수정
@OneToMany(mappedBy = "brand")
private List<BrandCategory> brandCategory;
그럼 실제로 service에서 수정해준다.
//1:N관계일 때(기존코드)
public List<BrandResponse> read(String category) {
List<Brand> categorySlug = brandRepository.findByCategorySlug(category);
return categorySlug.stream().map(brand -> new BrandResponse(
brand.getId(),
brand.getName(),
brand.getImageUrl()
)).toList();
}
// N:M관계일때
public List<BrandResponse> read(String category) {
List<BrandCategory> byCategorySlug = brandCategoryRepository.findByCategorySlug(category);
return byCategorySlug.stream().map(brandCategory ->
new BrandResponse(
brandCategory.getBrand().getId(),
brandCategory.getBrand().getName(),
brandCategory.getBrand().getImageUrl()
)).toList();
}
기존코드는 brandRepository로 활용하고 있지만, 이제는 brandcategory를 활용해서 가져오면 된다.
//1:n 관계
public BrandResponse oneBrandRead(Long brandId) {
Brand brand = brandRepository.findById(brandId).orElseThrow();
return new BrandResponse(brandId, brand.getName(), brand.getImageUrl());
}
//n:m
public BrandResponse oneBrandRead(Long brandId) {
BrandCategory brandCategory = brandCategoryRepository.findById(brandId).orElseThrow();
return new BrandResponse(
brandCategory.getBrand().getId(),
brandCategory.getBrand().getName(),
brandCategory.getBrand().getImageUrl());
}
이런식으로 작성된다.
😐 느낀점
N:M을 사용하기 위해서는 새로운 클래스가 필요하다.
이 클래스 자체는 어떤 중요한 역할을 하진 않지만, 이어주는 역할이기에 꼭 필요하다.
중간 다리의 repository도 꼭 필요하며 이걸 사용해서 보통 응용하면 된다.