Hibernate não pode simultaneamente buscar vários sacos

O Hibernate lança esta exceção durante a criação da SessionFactory:

org.hibernate.loader.MultipleBagFetchException: não pode buscar simultaneamente vários sacos

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 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 children; } 

AnotherParent.java

 @Entity public AntoherParent { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; @OneToMany(mappedBy="parent", fetch=FetchType.EAGER) private List anotherChildren; } 

O Hibernate não gosta de duas collections 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).

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 em torno 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 é mais apropriado que List , então a menos que você realmente precise de uma List – vá para Set

Basta mudar do tipo de List para o tipo de Set .

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 childs; 

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

Depois de tentar com todas as opções descritas neste posts e outros, cheguei à conclusão de que a correção é a seguinte.

Em cada lugar XToMany @ XXXToMany(mappedBy="parent", fetch=FetchType.EAGER) e intermediário após

 @Fetch(value = FetchMode.SUBSELECT) 

Isso funcionou para mim

Para consertá-lo, basta Set no lugar da List para o seu object nested.

 @OneToMany Set 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.

Eu encontrei uma boa postagem no blog sobre o comportamento do Hibernate neste tipo de mapeamento de objects: http://blog.eyallupu.com/2010/06/hibernate-exception-simultaneously.html

você pode manter listas EAGER de booth em JPA e adicionar a pelo menos uma delas a anotação JPA @OrderColumn (com obviamente o nome de um campo a ser ordenado). Não há necessidade de annotations específicas de hibernação. Mas tenha em mente que pode criar elementos vazios na lista se o campo escolhido não tiver valores a partir de 0

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

em Crianças, então você deve adicionar o campo orderIndex

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 .

Quando você tem objects muito complexos com a coleção de saver não poderia ser uma boa ideia ter todos eles com EAGER fetchType, use melhor o LAZY e quando você realmente precisar carregar as collections use: Hibernate.initialize(parent.child) para buscar os dados.

Nós tentamos Set em vez de List e é um pesadelo: quando você adiciona dois novos objects, equals () e hashCode () falham em distinguir ambos! Porque eles não têm nenhum id.

ferramentas típicas como o Eclipse geram esse tipo de código a partir das tabelas do Banco de Dados:

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

Você também pode ler este artigo que explica corretamente o quão fodido é o JPA / Hibernate. Depois de ler isto, acho que esta é a última vez que uso qualquer ORM na minha vida.

Eu também encontro caras do Domain Driven Design que basicamente dizem que o ORM é uma coisa terrível.

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.