source

휴지 상태에서는 MultipleBagFetchException이 느려짐 - 여러 개의 가방을 동시에 가져올 수 없음

factcode 2022. 9. 12. 11:35
반응형

휴지 상태에서는 MultipleBagFetchException이 느려짐 - 여러 개의 가방을 동시에 가져올 수 없음

휴지 상태에서는 SessionFactory 작성 중에 다음 예외가 발생합니다.

org.syslogate.syslog.syslog 를 지정합니다.MultipleBagFetchException: 여러 개의 가방을 동시에 가져올 수 없습니다.

테스트 케이스는 다음과 같습니다.

Parent.java

@Entity
public Parent {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private Long id;

 @OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
 // @IndexColumn(name="INDEX_COL") if I had this the problem solve but I retrieve more children than I have, one child is null.
 private List<Child> children;

}

Child.java

@Entity
public Child {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private Long id;

 @ManyToOne
 private Parent parent;

}

이 문제는 어떤가요?내가 뭘 할 수 있을까?


편집

네, 문제는 부모 안에 또 다른 '부모' 엔티티가 있다는 것입니다.제 실제 행동은 다음과 같습니다.

Parent.java

@Entity
public Parent {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private Long id;

 @ManyToOne
 private AnotherParent anotherParent;

 @OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
 private List<Child> children;

}

AnotherParent.java

@Entity
public AnotherParent {

 @Id
 @GeneratedValue(strategy=GenerationType.IDENTITY)
 private Long id;

 @OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
 private List<AnotherChild> anotherChildren;

}

최대 절전 모드 휴지 상태에서는과, 두번 수거 다음의 2개의 컬렉션을좋아하지 않습니다를 좋아하지 않는다.FetchType.EAGER,이 있었지만 그것은 벌레, 나는 특이한 것들 하고 있지 않아 보이는군요...하지만이건버그인 것 같아, 난 특이한 일을 하고 있지 않아...

삭제 중 제거FetchType.EAGER부터에서Parent또는 또는AnotherParent그러나 나는 그렇게 진정한 해결책문제는 해결되지만,저는그것이 필요하기 때문에,진정한 해결책은을 사용하는 것입니다 그것을 필요로 하는 문제 Solves.@LazyCollection(LazyCollectionOption.FALSE)대신 대신FetchType(솔루션의 Bozho 덕분입니다).

이것은 새로운 버전의 휴지 상태(JPA 2.0 지원)에서 처리할 수 있다고 생각합니다.그렇지 않으면 컬렉션 필드에 주석을 달아 해결할 수 있습니다.

@LazyCollection(LazyCollectionOption.FALSE)

그 반드시 삭제해 주세요를 제거하는 것을 기억하라.fetchType그 로부터의 어트리뷰트에서 특성@*ToMany주석.주석입니다.

하지만 노트 대부분의 경우에 있는하지만 대부분의 경우,.Set<Child>더 보다한 수준보다 적절하다List<Child>,라면 정말경우를 제외하고 필요한따라서 정말로가 필요하다.List - for -Set

그러나 세트를 사용한다고 해서 Vlad Mihalcea가 답변한 대로 기초가 되는 데카르트 제품을 제거할 수는 없습니다.

바꿔 ListSetdiscloss.discloss.

그러나 Vlad Mihalcea가 그의 답변에서 설명한 것처럼 기초가 되는 데카르트 제품을 제거하지는 않을 것임을 상기시켜라!

코드에 휴지 상태 고유의 @Fetch 주석을 추가합니다.

@OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT)
private List<Child> childs;

그러면 휴지 상태 버그 HH-1718과 관련된 문제가 해결됩니다.

다음과 같은 엔티티가 있는 것을 고려합니다.

여기에 이미지 설명 입력

어떤 합니다.Post comments ★★★★★★★★★★★★★★★★★」tags★★★★★★ 。

의 「」를 .JOIN FETCH★★★★

List<Post> posts = entityManager
.createQuery(
    "select p " +
    "from Post p " +
    "left join fetch p.comments " +
    "left join fetch p.tags " +
    "where p.id between :minId and :maxId", Post.class)
.setParameter("minId", 1L)
.setParameter("maxId", 50L)
.getResultList();

하이버네이트는 악명 높은 것을 던집니다.

org.hibernate.loader.MultipleBagFetchException: cannot simultaneously fetch multiple bags [
  com.vladmihalcea.book.hpjp.hibernate.fetching.Post.comments,
  com.vladmihalcea.book.hpjp.hibernate.fetching.Post.tags
]

휴지 상태에서는 데카르트 제품이 생성되기 때문에 한 개 이상의 가방을 가져올 수 없습니다.

최악의 '솔루션

많은 투고,볼 수 .SetList를 참조해 주세요.

그건 끔찍한 충고야.그렇게 하지 마.

「」를 사용합니다.SetsLists를 만듭니다.MultipleBagFetchException이 "수정"을 적용한 지 오래 후에 성능 문제를 발견하게 되므로 데카르트 제품은 그대로 유지됩니다.

적절한 해결책

다음의 트릭을 실행할 수 있습니다.

List<Post> posts = entityManager
.createQuery(
    "select distinct p " +
    "from Post p " +
    "left join fetch p.comments " +
    "where p.id between :minId and :maxId ", Post.class)
.setParameter("minId", 1L)
.setParameter("maxId", 50L)
.setHint(QueryHints.PASS_DISTINCT_THROUGH, false)
.getResultList();

posts = entityManager
.createQuery(
    "select distinct p " +
    "from Post p " +
    "left join fetch p.tags t " +
    "where p in :posts ", Post.class)
.setParameter("posts", posts)
.setHint(QueryHints.PASS_DISTINCT_THROUGH, false)
.getResultList();

번째 에서는 "JPQL" 입니다.distinctSQL の sql sql sql sql sql 。에 우리는 렇렇 the the the the the 를 설정했습니다.PASS_DISTINCT_THROUGH에 JPA 힌트false.

두 가지 , DISTINT에서 합니다.여기서 JPQL은 에서 반환된 Java 객체 참조를 중복 배제하기 위해 필요합니다.getResultListSQL Java를 사용합니다.

를 사용하여 .JOIN FETCH

여러 쿼리를 사용하면 첫 번째 컬렉션을 제외한 다른 컬렉션은 보조 쿼리를 사용하여 가져오기 때문에 데카르트 제품을 피할 수 있습니다.

네가 할 수 있는 일이 더 있어

'아예'를한다면,FetchType.EAGER@OneToMany ★★★★★★★★★★★★★★★★★」@ManyToMany 쉽게 '', '연상', '연상'이 나올 도 있어요.MultipleBagFetchException.

'바꾸다'에서 게.FetchType.EAGER로로 합니다.Fetchype.LAZY신속한 취득은 중대한 애플리케이션 성능 문제로 이어질 수 있는 끔찍한 아이디어이기 때문입니다.

결론

FetchType.EAGER하지 마세요.List로로 합니다.Set가 하이버네이트를 수 있기 때문에 하이버네이트는 하이버네이트를 숨깁니다.MultipleBagFetchException에 한 한 번에 한 수집품만 가져오면 괜찮을 거야.

초기화할 컬렉션이 있는 것과 동일한 수의 쿼리를 사용하면 됩니다.루프에서 수집을 초기화하지 마십시오. 그러면 N+1 쿼리 문제가 발생하므로 성능에도 좋지 않습니다.

이 투고 등에 기재되어 있는 모든 옵션을 시험해 본 결과, 수정은 다음과 같은 결론에 도달했습니다.

장소@ 든 xt xt XTo @XXXToMany(mappedBy="parent", fetch=FetchType.EAGER) 중간 에.

@Fetch(value = FetchMode.SUBSELECT)

이건 내게 효과가 있었다.

하려면 , 해 주세요.SetList이치노

@OneToMany
Set<Your_object> objectList;

잊지 꼭 쓰세요.fetch=FetchType.EAGER

그건 작동할 것이다.

의 개념이 .CollectionId목록만 유지하려면 최대 절전 모드로 전환하십시오.

그러나 Vlad Mihalcea가 그의 답변에서 설명한 것처럼 기초가 되는 데카르트 제품을 제거하지는 않을 것임을 상기시켜라!

이러한 오브젝트 맵핑에서의 휴지 상태의 동작에 관한 블로그 투고를 찾았습니다.http://blog.eyallupu.com/2010/06/hibernate-exception-simultaneously.html

부스 OVER 목록을 JPA에 보관하고 그 중 하나 이상에 JPA 주석 @OrderColumn을 추가할 수 있습니다(주문할 필드 이름 포함).특정 휴지 상태 주석이 필요하지 않습니다.단, 선택한 필드에 0부터 시작하는 값이 없을 경우 목록에 빈 요소가 생성될 수 있습니다.

 [...]
 @OneToMany(mappedBy="parent", fetch=FetchType.EAGER)
 @OrderColumn(name="orderIndex")
 private List<Child> children;
 [...]

Children에서 orderIndex 필드를 추가해야 합니다.

List 대신 Set을 시도했지만 악몽입니다.새로운 오브젝트를 2개 추가하면 equals()와 hashCode()가 양쪽을 구별하지 못합니다.아이디가 없기 때문입니다.

Eclipse와 같은 일반적인 도구는 데이터베이스 테이블에서 이러한 종류의 코드를 생성합니다.

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((id == null) ? 0 : id.hashCode());
    return result;
}

JPA/Hibernate가 얼마나 엉망인지 설명하는 이 기사를 읽을 수도 있습니다.이 글을 읽고 난 후, 내 인생에서 ORM을 사용하는 것은 이번이 마지막인 것 같다.

도메인 기반 설계 담당자도 ORM은 기본적으로 끔찍하다고 말합니다.

을 가진 복잡한 을 사용하는을 실제로 가 있는 saveral fetchType을 합니다.또한 컬렉션을 로드해야 할 때는 다음과 같이 사용하는 것이 좋습니다.Hibernate.initialize(parent.child)데이터를 가져옵니다.

문제는 네스트된 EIGER 페치를 갖는 것이었습니다.

해결 방법 중 하나는 네스트된 필드를 LAGY로 설정하고 휴지 상태를 사용하는 것입니다.initialize()를 사용하여 네스트된 필드를 로드합니다.

x = session.get(ClassName.class, id);
Hibernate.initialize(x.getNestedField());

이 문제는 FetchType을 사용하여 여러 컬렉션을 수집했을 때 발생했습니다.열심, 이렇게

@ManyToMany(fetch = FetchType.EAGER, targetEntity = className.class)
@JoinColumn(name = "myClass_id")
@JsonView(SerializationView.Summary.class)
private Collection<Model> ModelObjects;

또한 컬렉션은 같은 열에 결합되어 있었습니다.

이 문제를 해결하기 위해 컬렉션 중 하나를 FetchType으로 변경했습니다.제 사용 예로는 괜찮았기 때문에 게으름 피웠습니다.

행운을 빕니다.~J

Fetch ★★★★★★★★★★★★★★★★★」LazyCollection을 사용하다

@Fetch(FetchMode.JOIN)
@LazyCollection(LazyCollectionOption.FALSE)

★★★★★★★★★★★★★★★의 장점 중 @LazyCollection(LazyCollectionOption.FALSE) 여러 할 수 .FetchType.EAGER그러한 공존이 정당한 상황에서도 할 수 없다.

를 들면, 「」라고 하는 은,Order가 수 OrderGroup 것)및 (짧은 것) Promotions(서양속담, 돈속담) @LazyCollection(LazyCollectionOption.FALSE)이 되지 할 수 LazyInitializationException 다 아니다MultipleBagFetchException.

같은 에는 ★★★★★★★★★★★★★★★★★★★★★★★.@FetchMultipleBacFetchException후, 「」의 원인이 됩니다.LazyInitializationException, , , ,.no Session

주석을 달아 해결했습니다.

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)

좋아, 여기 내 2센트야.엔티티에 Fetch Lazy 주석이 있었지만 세션빈에서 Fetch Lazy 주석을 복제했기 때문에 여러 개의 가방 문제가 발생했습니다.SessionBean에서 행을 삭제했습니다.

criteria.createAlias()필드", "ALIAS", JoinType.왼쪽_OUTER_JOIN); //삭제 완료

그리고 나는 하이버네이트를 썼다.List parent = criteria.list가 호출된 후 가져올 목록에서 초기화합니다.동면하다.initialize(parent.getChildList());

fetch=PerchType으로 할 수도 있습니다.LAGY를 사용하여 아이를 얻는 메서드에 @Transactional(readOnly = true)을 추가합니다.

이 문제를 해결하려면 새 주석을 사용할 수 있습니다.

@XXXToXXX(targetEntity = XXXX.class, fetch = FetchType.LAZY)

실제로 fetch의 기본값은 FetchType입니다.게으름도 피우고

언급URL : https://stackoverflow.com/questions/4334970/hibernate-throws-multiplebagfetchexception-cannot-simultaneously-fetch-multipl

반응형