É comum termos um entidade que precise carregar mais de uma lista, e quando essas listas precisam ser carregadas juntas no mesmo select, podemos nos deparar com o seguinte erro:
Caused by: org.hibernate.loader.MultipleBagFetchException:
cannot simultaneously fetch multiple bags
Bag significa algo como "bolsa" ou "sacola" (tradução livre rsrsrs), e isso quer dizer estamos tentando carregar mais de uma "bolsa" de dados e o JPA não sabe como organizar esses dados para nos entregar.
Isso ocorre porque geralmente o banco nos devolve uma lista ordenada de dados (List), mas como o JPA está tentando montar uma lista que contém listas dentro delas, ele pode acabar desordenando essas listas. Então ele quer que você diga pra ele como tratar esses dados.
Existem basicamente 3 formas de contornarmos esse problema:
- Nunca carregar as listas na mesma consulta.
- Usar Set ao invés de List ao criar as listas na entidade.
- Usando a anotação @OrderColumn.
1 - Nunca carregar as listas na mesma consulta.
Ao invés de você usar o FetchType.EAGER ou no select fazer um join fetch caso o carregamento seja FetchType.LAZY nas "n" listas da sua entidade, você carrega apenas uma delas no primeiro momento, e a(s) outra(s) você carrega separadamente, por exemplo chamando o método get da(s) outra(s) lista(s) com o objeto ainda gerenciado pelo JPA, de forma que ele vá ao banco e preencha essas listas.
2 - Usar Set ao invés de List ao criar as listas na entidade.
Outra solução é usar o Set ao invés do List. Como o Set não é ordenado como o List o JPA não vai se perder tentando ordenar essa lista. Lembrando que o Set não trabalha com dados duplicados.
3 - Usando a anotação @OrderColumn.
Você também pode criar um campo para o hibernate trabalhar a ordenação e não se perder. A desvantagem dessa solução é unicamente a de criar um campo extra para o JPA poder ordenar os dados.
Se o mapeamento for bidirecional, será preciso criar a propriedade e mapea-la na classe que detêm o mapeamento além de usá-la no @orderColumn.
@Entity public class Paciente {
//se tiver o mappedBy (bidirecional) precisa criar a propriedade na outra classe @OneToMany(mappedBy="paciente") @OrderColumn(name="ordenacao_hibernate") private List<PacienteSintoma> lstPacienteSintoma;
//se tiver o mappedBy (bidirecional) precisa criar a propriedade na outra classe
@OneToMany(mappedBy="paciente")
@OrderColumn(name="ordenacao_hibernate")
private List<PacienteDiagnostico> lstPacienteDiagnostico;
... } @Entity public class PacienteSintoma { ... //bidirecional, necessário mapear a propriedade @Column(name="ordenacao_hibernate") private int ordenacaoHibernate; @ManyToOne @JoinColumn(name="paciente_id", nullable=false) private Paciente paciente;
... }
@Entity public class PacienteDiagnostico { ... //bidirecional, necessário mapear a propriedade @Column(name="ordenacao_hibernate") private int ordenacaoHibernate; @ManyToOne @JoinColumn(name="paciente_id", nullable=false) private Paciente paciente;
...
}
Se o mapeamento for unidirecional, será preciso criar apenas o campo no banco e passá-lo no @orderColumn.
@Entity public class Paciente {
//unidirecional @OneToMany
@JoinColumn(name="paciente_id", nullable=false) @OrderColumn(name="ordenacao_hibernate") private List<PacienteSintoma> lstPacienteSintoma;
//se tiver o mappedBy (bidirecional) precisa criar a propriedade na outra classe
@OneToMany(mappedBy="paciente")
@JoinColumn(name="paciente_id", nullable=false)
@OrderColumn(name="ordenacao_hibernate")
private List<PacienteDiagnostico> lstPacienteDiagnostico;
... } @Entity public class PacienteSintoma { ... //bidirecional, necessário mapear a propriedade @Column(name="ordenacao_hibernate") private int ordenacaoHibernate; @ManyToOne @JoinColumn(name="paciente_id", nullable=false, insertable=false, updatable=false) private Paciente paciente;
... }
@Entity public class PacienteDiagnostico { ... //bidirecional, necessário mapear a propriedade @Column(name="ordenacao_hibernate") private int ordenacaoHibernate; @ManyToOne @JoinColumn(name="paciente_id", nullable=false, insertable=false, updatable=false) private Paciente paciente;
...
}
Fonte: https://docs.jboss.org/hibernate/stable/annotations/reference/en/html/entity.html#entity-hibspec-collection-extratype-indexbidir
Nenhum comentário:
Postar um comentário