javax - Hibernate não pode buscar simultaneamente vários sacos




javax persistence entitymanager example (8)

A razão pela qual você obtém essa exceção é que o Hibernate acabaria fazendo um Produto Cartesiano que é ruim para o desempenho.

Agora, embora você possa "consertar" o problema usando Set vez de List , você não deve fazer isso porque o Produto Cartesiano ainda será apresentado nas instruções SQL subjacentes.

É melhor alternar de FetchType.EAGER para Fetchype.LAZY pois a busca ansiosa é uma ideia terrível que pode levar a problemas críticos de desempenho do aplicativo .

Se você precisar buscar as entidades filho em uma hierarquia de vários níveis, selecione melhor da criança mais interna até os pais, conforme explicado neste artigo .

O Hibernate lança essa exceção durante a criação de SessionFactory:

org.hibernate.loader.MultipleBagFetchException: não pode buscar simultaneamente várias malas

Este é o meu caso de teste:

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;

}

Como sobre esse problema? O que eu posso fazer?

EDITAR

OK, o problema que tenho é que outra entidade "pai" está dentro do meu pai, meu comportamento real é este:

Parent.java

@Entity
public Parent {

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

 @ManyToOne
 private AntoherParent anotherParent;

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

}

AnotherParent.java

@Entity
public AntoherParent {

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

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

}

O Hibernate não gosta de duas coleções com o FetchType.EAGER , mas isso parece ser um bug, eu não estou fazendo coisas incomuns ...

Removendo FetchType.EAGER de Parent ou AnotherParent resolve o problema, mas eu preciso disso, então a solução real é usar @LazyCollection(LazyCollectionOption.FALSE) vez de FetchType (graças a Bozho para a solução).


Como alternativa, adicione uma anotação @Fetch específica do Hibernate ao seu código:

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

Isso deve corrigir o problema, relacionado ao bug do Hibernate HHH-1718


Eu acho que uma nova versão do hibernate (suporte a JPA 2.0) deve lidar com isso. Mas, caso contrário, você pode trabalhar ao redor anotando os campos de coleta com:

@LazyCollection(LazyCollectionOption.FALSE)

Lembre-se de remover o atributo @*ToMany anotação @*ToMany .

Mas note que na maioria dos casos um Set<Child> é mais apropriado que List<Child> , então a menos que você realmente precise de uma List - vá para Set



Para consertá-lo, basta Set no lugar de List para o seu objeto aninhado.

@OneToMany
Set<Your_object> objectList;

e não se esqueça de usar fetch=FetchType.EAGER

vai funcionar.

Há mais um conceito CollectionId no Hibernate se você quiser ficar apenas com a lista.


Para mim, o problema era ter buscas EAGER aninhadas.

Uma solução é definir os campos aninhados para LAZY e usar o Hibernate.initialize () para carregar o (s) campo (s) aninhado (s):

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

Simplesmente mude do tipo de List para o tipo de Set .


Você poderia usar uma nova anotação para resolver isso:

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

Na verdade, o valor padrão da busca é FetchType.LAZY também.







java-persistence-api