[MapStruct] LazyInitializationException: failed to lazily initialize a collection of role
문제 상황
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: fittering.mall.domain.entity.Mall.favorites: could not initialize proxy - no Session
프로젝트에서 MapStruct를 통해 DTO와 일부 파라미터를 함께 조합해서 Product
엔티티 객체를 생성하는 로직에서 예외가 발생
했다. Product
내에 favorites
필드가 Favorite
과 연관관계를 맺고 있어서 이를 초기화해주는 로직을 MapStruct에서
만들어줬고, 애플리케이션 실행 후 해당 로직을 테스트하는 과정에서 문제가 발생했다.
//MapStruct Mapper에 정의된 함수
public Product toProduct(CrawledProductDto crawledProductDto, String image, Integer view, Integer timeView, Category category, SubCategory subCategory, Mall mall) {
if ( crawledProductDto == null && image == null && view == null && timeView == null && category == null && subCategory == null && mall == null ) {
return null;
}
//ProductMapperImpl에 정의된 롲기
Product.ProductBuilder product = Product.builder();
if ( crawledProductDto != null ) {
product.name( crawledProductDto.getName() );
product.origin( crawledProductDto.getUrl() );
product.price( crawledProductDto.getPrice() );
product.gender( crawledProductDto.getGender() );
product.type( crawledProductDto.getType() );
product.disabled( crawledProductDto.getDisabled() );
}
if ( mall != null ) {
product.mall( mallToMall( mall ) );
product.image( mall.getImage() );
List<Favorite> list = mall.getFavorites(); //favorites를 초기화 해주고 있음
if ( list != null ) {
product.favorites( new ArrayList<Favorite>( list ) );
}
}
//Product 엔티티 정보
public class Product {
@Id @GeneratedValue
@Column(name = "product_id")
private Long id;
@NonNull @Length(max = 50)
private String name;
@OneToMany(mappedBy = "product")
private List<Favorite> favorites = new ArrayList<>();
...
}
해결
Product
에서 Favorite
을 지연 로딩때문에 프록시로 들고왔는데 초기화 로직을 수행해야해서 트랜잭션이 필요했다.
하지만 해당 로직이 포함된 함수에서는 DB 데이터를 수정하는 작업이 있으므로 @Transactional
을 설정해주니 해결할 수 있었다.
@Transactional //추가
public void updateCrawledProducts(...) {
Product product = save(ProductMapper.INSTANCE.toProduct(
productDto, thumbnail, 0, 0, category, subCategory, mall));
...
}
댓글남기기