인프런 커뮤니티 질문&답변

김동영님의 프로필 이미지
김동영

작성한 질문수

코드로 배우는 React with 스프링부트 API서버

서비스계층과 컨트롤러(1) - 상품 목록/등록

Entity에 ElementCollection이 두 개 있는 경우

작성

·

174

0

안녕하세요! 하나의 엔티티에 @ElementCollection 붙은 필드가 두 개 있는 경우를 시험해 보고 있습니다. @EntityGraph(attributePaths = {"a", "b"}) 이런 식으로 해서 테스트를 돌리면 org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags 과 같은 오류가 나는데 ElementCollection 두 개가 있는 경우는 하나의 쿼리로 모두 가져오는 방법은 없나요?

답변 1

0

구멍가게코딩단님의 프로필 이미지
구멍가게코딩단
지식공유자

말씀하신 내용은 https://jojoldu.tistory.com/457

인데 @ElementCollection으로 적용하시는 거죠?

 

음..BatchSize를 지정했던 것으로 기억하는데.. 저녁에 조금 더 살펴보고 댓글 남기겠습니다.

 

우선은 이런 방법도 있으니...

 

https://stackoverflow.com/questions/49127043/multiple-elementcollections-with-jpa-error-persistenceunit-jpa-unable-to

김동영님의 프로필 이미지
김동영
질문자

빠른 답변 감사합니다! 아래 따라 해봤는데 안되는 것 같아요...

구멍가게코딩단님의 프로필 이미지
구멍가게코딩단
지식공유자

package com.example.demo.entity;


import jakarta.persistence.*;
import lombok.*;

@Entity
@Table(name = "tbl_todos")
@Getter
@AllArgsConstructor
@NoArgsConstructor
@ToString(exclude = {"tags", "files"})
@Builder
public class TodoEntity {

    @Id
    @GeneratedValue(strategy = jakarta.persistence.GenerationType.IDENTITY)
    private Long tno;

    private String title;

    private boolean complete;


    @ElementCollection(fetch = FetchType.LAZY)
    @CollectionTable(name = "tbl_todo_tags")
    @Builder.Default
    private java.util.Set<String> tags = new java.util.HashSet<>();

    @ElementCollection(fetch = FetchType.LAZY)
    @CollectionTable(name = "tbl_todo_files")
    @Builder.Default
    private java.util.Set<String> files = new java.util.HashSet<>();

    public void addTag(String tag) {
        tags.add(tag);
    }

    public void addFile(String file) {
        files.add(file);
    }

    public void removeTags() {
        tags.clear();
    }

    public void removeFiles() {
        files.clear();
    }


    public void changeTitle(String title) {
        this.title = title;
    }

    public void changeComplete(boolean complete) {
        this.complete = complete;
    }

}
public interface TodoRepository extends JpaRepository<TodoEntity, Long>{


    @EntityGraph(attributePaths = {"tags", "files"}, type = EntityGraph.EntityGraphType.FETCH)
    @Query("select t from TodoEntity t where t.tno = :tno")
    Optional<TodoEntity> findByTno(Long tno);

}

List 대신에 Set으로 하셔야 Bag관련 에러가 발생하지 않습니다.

 

@Test
@Transactional
public void testRead() {
    Long tno = 1L;

    todoRepository.findByTno(tno).ifPresent(todo -> {
        System.out.println(todo);
        System.out.println(todo.getTags());
        System.out.println(todo.getFiles());
    });
}


결과---------------------------------------
Hibernate: 
    select
        te1_0.tno,
        te1_0.complete,
        f1_0.todo_entity_tno,
        f1_0.files,
        t1_0.todo_entity_tno,
        t1_0.tags,
        te1_0.title 
    from
        tbl_todos te1_0 
    left join
        tbl_todo_files f1_0 
            on te1_0.tno=f1_0.todo_entity_tno 
    left join
        tbl_todo_tags t1_0 
            on te1_0.tno=t1_0.todo_entity_tno 
    where
        te1_0.tno=?
TodoEntity(tno=1, title=Sample...0, complete=false)
[t1, t2]
[f1, f2]
김동영님의 프로필 이미지
김동영
질문자

정말 감사합니다!! 좋은 밤 되십시오!!

김동영님의 프로필 이미지
김동영

작성한 질문수

질문하기