Erro em relacionamento Manytomany no Hibernate

Asked

Viewed 840 times

1

I have a problem with @manyToMany. You’re making the mistake:

org.hibernate.Multiplebagfetchexception: cannot simultaneously fetch Multiple bags

Follows my model:

@Entity
@Table(name = "sar_evento", schema = "sar")
@SequenceGenerator(name = "sequence", sequenceName = "sar.evento_sequence", schema = "sar")
public class Evento implements Serializable, BaseEntity {

    @Id
    @GeneratedValue(generator = "sequence", strategy = GenerationType.AUTO)
    @Column(name = "id_evento", nullable = false, unique = true)
    private Long id;

    @Column(length = 255)
    private String nome;

    @Column(columnDefinition = "text")
    private String descricao;

    @Column(name = "data_inicio")
    @Temporal(TemporalType.TIMESTAMP)
    private Date dataInicio;

    @Column(name = "data_fim")
    @Temporal(TemporalType.TIMESTAMP)
    private Date dataFim;

    @Column(name = "dia_todo")
    private boolean diaTodo;

    @ManyToOne
    @JoinColumn(name = "id_sala", referencedColumnName = "id_sala")
    private Sala sala;

    @ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
    @OrderBy("nome asc")
    @JoinTable(name = "sar_evento_recurso", schema = "sar",
            joinColumns = {
                @JoinColumn(name = "id_evento")},
            inverseJoinColumns = {
                @JoinColumn(name = "id_recurso")})
    private List<Recurso> recursos = new ArrayList<Recurso>();

    @ManyToOne
    @JoinColumn(name = "id_usuario", referencedColumnName = "id")
    private Usuario usuario;

someone’s been through this trouble?

1 answer

1


This error refers to cases where a query performed in JPA or Hibernate uses the fetch Join in more than one relationship.

The joins "normal", Lazy and Eager, bring the related lists in commands SELECT subsequent to the SELECT main, ie, it retrieves first the requested entity, then the data of your relationships.

This means that, in terms of performance, the mode Lazy and the way ager are equivalent. The difference is that the Lazy expects a method getter be invoked to execute the other queries while in mode ager they are executed right after the main.

Already the fetch Join force a Join native to the database, already retrieving both the main entity and related entities. This is usually used for optimization purposes.

However, Hibernate only supports performing the fetch Join in a related table. If you try to do more than one, the indicated error will occur.

The reason is quite simple when you think about what the result of query multi-jointed.

For example, let’s assume that you try to retrieve a list from the entity Evento and does the fetch Join with Recurso. If there is N events and M resources for each event the query will return N x M results, in which data from Evento will be repeated for each record of the respective Recurso.

Now, if we try to add any more relationships, for example Sala, your values will also be repeated N x M x K times.

In addition to the performance of the query starting to look bad, another problem emerges: it is very complicated to process the result of the query and identify which values repeat and which should create another entity in the list.

The solution is to recover these relationships in separate queries and not try to do everything at once.

  • Only by complementing, changing from List to Set should solve the problem: http://stackoverflow.com/questions/4334970/hibernate-cannot-simultaneously-fetch-multiple-bags

  • Hello I changed my relationship to: @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @OrderBy("nome asc") @JoinTable(name = "sar_evento_recurso", schema = "sar", joinColumns = { @JoinColumn(name = "id_evento")}, inverseJoinColumns = { @JoinColumn(name = "id_recurso")}) private List<Recurso> recursos = new ArrayList<Recurso>();. Now I’m having trouble with session: org.hibernate.LazyInitializationException: failed to lazily initialize a collection, no session or session was closed.

  • @Josuéeduardo Apparently, change to Set really avoids the problem, but it is important to emphasize that Set and List are not equivalent structures. In the case of this issue, there is a @OrderBy in the relationship. With the Set, there is no guarantee that the order will be respected.

  • 1

    @paulohddias Try to solve by going back to FetchType.EAGER and adding the annotation @Fetch(FetchMode.SELECT). This will cause the list to be retrieved in a SELECT later, avoiding problems with joins.

  • I switched to :@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)&#xA; @Fetch(FetchMode.SELECT)&#xA; @JoinTable(name = "sar_evento_recurso", schema = "sar",&#xA; joinColumns = {&#xA; @JoinColumn(name = "id_evento")},&#xA; inverseJoinColumns = {&#xA; @JoinColumn(name = "id_recurso")})&#xA; private Set<Recurso> recursos = new HashSet<Recurso>();. But I keep having session error when I try to change or delete, to insert this all ok.

  • @paulohddias Regarding the error of LazyInitializationException, are you sure it’s not in other relationships? Try putting EAGER for everything you are using in the change and removal.

  • All with EAGER

  • and the mistake is in this relationship because without it I get normal

  • @paulohddias The code that is in your question is not all with ager. Also, the fact that you take out this relationship makes the code work doesn’t mean that the mistake is just in it. As I explained in the answer, error occurs when there is more than one relationship.

  • so the start error no longer happens when I switched to set and put @Fetch(Fetchmode.SELECT) the problem is now in the session I am using jpa and I tried to create opensessionview and it is no use

  • I’m lost I don’t know what to do

  • 1

    I got thank you the error was in the view in jsf, of course after I tidied up manyTomany as you said I had to put not my f:selectItems the <f:attribute name="collectionType" value="java.util.Hashset" /> dai got the session error thank you very much for the help

Show 7 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.