HIBERNATE : cannot simultaneously fetch multiple bags

Boa tarde !

Antes de postar esta dúvida fiz uma pesquisa no fórum sobre este problema. Não há achei nenhuma solução esclarecedora.
A Classe abaixo OBRAS possui um relacionamento 1:N com as classes ObraAcessibilidade e ObraProfissionais.

 
package br.jus.trems.obras.entidades;
import br.jus.trems.admSistemas.entidades.Servidor;
import br.jus.trems.obras.service.ObraProfissionaisService;
import br.jus.trems.obras.service.impl.ObraProfissionaisServiceImpl;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.*;
 
@Entity
@Table(name = "OBRAS")
public class Obra implements Serializable {
   @Id
   @Column(name="ID")
   @GeneratedValue(generator = "ObraSeq", strategy = GenerationType.SEQUENCE)
   @SequenceGenerator(name = "ObraSeq", sequenceName = "SCO_SEQUENCE", allocationSize = 1)
   private Integer id;
   @Column(name="NM_DESCRICAO")
   private String descricao;
   @ManyToOne
   @JoinColumn(name="ID_UNIDADE")
   private UnidadeTre unidadetre;
   @ManyToOne
   @JoinColumn(name="ID_COMUNICACAO")
   private Comunicacao comunicacao;
 
   @Column(name="DS_ENDERECO")
   private String endereco;
   @ManyToOne
   @JoinColumn(name="ID_CIDADE")
   private Cidade cidade;
   @Column(name="NR_CEP")
   private String cep;
   @Column(name="GR_LATITUDE")
   private String latitude;
   @Column(name="GR_LONGITUDE")
   private String longitude;
   @Column(name="DS_LEI_DOACAO_TERRENO")
   private String leidoacaoterreno;

   @OneToMany(mappedBy="obra", cascade= CascadeType.ALL, fetch=FetchType.EAGER)
   @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
   private List<ObraAcessibilidade> obraacessibilidades = new ArrayList<ObraAcessibilidade>();
 
   @OneToMany(mappedBy="obra", cascade= CascadeType.ALL, fetch=FetchType.LAZY)
   @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
   private List<ObraProfissionais> obraprofissionais = new ArrayList<ObraProfissionais>();
 

Ocorre que se atribuir o fetch como EAGER para ambas ocorre o erro abaixo :

Se deixo somente a classe ObraProfissionais como LAZY :

Alterei os LIST por Set mas ocorre o erro “Idenficador Inválido”.

Alguém se habilita ?

[]s

Em um post anterior já foi citado este link, que explica porque acontece:
http://www.jroller.com/eyallupu/entry/hibernate_exception_simultaneously_fetch_multiple

A solução proposta que achei mais interessante foi esta:
http://www.jroller.com/eyallupu/entry/solving_simultaneously_fetch_multiple_bags

Pelo que entendi é para tirar da anotação @OneToMany o ‘mappedBy’, fazendo com que ele deixe de ser considerado pelo hibernate como um ‘bag’ e incluir a anotação @IndexColumn(name=“nome_da_sua_coluna_ID”):

@OneToMany(cascade= CascadeType.ALL, fetch=FetchType.EAGER) @IndexColumn(name="ID_OBRA") //<-- substitua pelo nome correto da coluna @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) private List<ObraAcessibilidade> obraacessibilidades = new ArrayList<ObraAcessibilidade>();
Boa sorte!

Obrigado Jamir !

Neste link são apresentadas 3 soluções. Fiquei com uma 4 solução apresentada em um comentário sobre as técnicas.

  @OneToMany(mappedBy="obra", cascade= CascadeType.ALL)
  @LazyCollection(LazyCollectionOption.FALSE)    
  @org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)   
  private List<ObraProfissionais> obraprofissionais = new ArrayList<ObraProfissionais>();  

Valeu.

Apenas para acrescentar, comigo estava acontecendo este mesmo erro. Resolvi apenas alterando o mapeamento de FetchType.EAGER para Lazy

Eu me equivoquei na resposta acima. Uma boa alternativa que eu encontrei foi alterar o List para Set e pronto, utilizando a estrutura do @OneToMany com mappedBy


@OneToMany(mappedBy="obra", cascade= CascadeType.ALL)  
@org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)     
private Set<ObraProfissionais> obraprofissionais = new HashSet<ObraProfissionais>();    

Resolveu aqui também! Obrigado! :slight_smile:

Até +!

[quote=duducordeiro_]Eu me equivoquei na resposta acima. Uma boa alternativa que eu encontrei foi alterar o List para Set e pronto, utilizando a estrutura do @OneToMany com mappedBy


@OneToMany(mappedBy="obra", cascade= CascadeType.ALL)  
@org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)     
private Set<ObraProfissionais> obraprofissionais = new HashSet<ObraProfissionais>();    

[/quote]

Olá, aqui resolveu também, colocando Set no lugar de List.

Alguém sabe o porque disso? Obrigado

aqui resolveu o problema do bags , mas com o set ele só lista 1 item devido a informação que vem do banco da classe pai repetir no caso vendas e item vendas onde em item vai repetir o codigo venda_id

[quote=thiagocastanhari][quote=duducordeiro_]Eu me equivoquei na resposta acima. Uma boa alternativa que eu encontrei foi alterar o List para Set e pronto, utilizando a estrutura do @OneToMany com mappedBy


@OneToMany(mappedBy="obra", cascade= CascadeType.ALL)  
@org.hibernate.annotations.Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN)     
private Set<ObraProfissionais> obraprofissionais = new HashSet<ObraProfissionais>();    

[/quote]

Olá, aqui resolveu também, colocando Set no lugar de List.

Alguém sabe o porque disso? Obrigado[/quote]


Olá, cheguei tarde mas talvez ajude alguém…

A especificação JPA não permite que em uma classe do tipo bean de entidade sejam utilizados dois relacionamentos com fetch igual a FetchType.EAGER, sendo esses do tipo das interfaces List e Collection. Assim, para contornar essa limitação definimos um dos relacionamentos como um objeto do tipo da interface Set.

Bons estudos!

Resolvi adicionando @Fetch(FetchMode.SUBSELECT) abaixo do @OneToMany(fetch = FetchType.EAGER).

1 curtida

Putz cara !!! tu é um anjo??? kkkk . . .melhor solução pra mim aqui!! espero que seja a mais performatica tbem!
Se eu mudasse pra SET, teria que mudar o JSP e mais outras coisa, além que com SET ele tava duplicando registro… enfim, prun novato igual eu sua solução foi espetacular, caiu como uma luva…

valewWW!!!

abrç´s

Putz cara !!! tu é um anjo??? kkkk . . .melhor solução pra mim aqui!! espero que seja a mais performatica tbem!
Se eu mudasse pra SET, teria que mudar o JSP e mais outras coisa, além que com SET ele tava duplicando registro… enfim, prun novato igual eu sua solução foi espetacular, caiu como uma luva…

valewWW!!!

abrç´s[/quote]
Só lembre de deixar claro que você está respondendo a um tópico antigo.

E mais umas ressalvas:

Tome cuidado porque a anotação @Fetch é específica do Hibernate, se você precisar utilizar JPA puro, não poderá utilizar assim.
E eu garanto que o seu Set não está duplicando registros, o que pode acontecer é seu equals não estar corretamente sobrescrito

resolveu aqui pra mim também, ainda mantive o List<>.

esse topico foi muito importante pra mim, testei todas as opções, mas a unica que funcionou comigo, foi usar o Set ao invés de collection.

Também resolvi desta forma.

Ola wmaciel, eu tambem tive praticamente o mesmo erro, mas resolvi colocando o fetch = FetchType.EAGER e tambem adicionando a anotacao @Fetch(value = FetchMode.SUBSELECT).

Exemplo:

@OneToMany(mappedBy="parent", fetch=FetchType.EAGER) @Fetch(value = FetchMode.SUBSELECT) private List<ObraAcessibilidade> obraAcessibilidade = new ArrayList<>();

Espero que ajude…

Aqui funcionou também. Valeu!

Resolvido para mim também, o meu ficou assim:

@OneToMany(mappedBy = “pessoaFisica”,fetch=FetchType.EAGER) @Fetch(value=org.hibernate.annotations.FetchMode.SUBSELECT)