3
Hello.
I’m having trouble getting my relationships fetch = Fetchtype.LAZY to work with the @Onetomany annotation. In my Notafiscal entity, there are several lists fetch = Fetchtype.LAZY, when loading the object by id, I load all these lists with left Outer Join. In the first instance (debugging) all lists are loaded. However, the moment I change tab and the request of the mailing list (mailing list) is returning me the error:
org.hibernate.Lazyinitializationexception: failed to lazily initialize a Collection of role: br.inf.criar.erp.nota.domain.Notafiscal.listaEmail, could not initialize proxy - no Session
To try to explain better, follows part of the Notafiscal class
@Entity
@Table(name = "notas_fiscais")
public class NotaFiscal implements IEntity {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@OneToMany(mappedBy = "notaFiscal", fetch = FetchType.LAZY,
cascade = {CascadeType.ALL},
orphanRemoval = true)
private List<NotaFiscalItem> itens;
@OneToMany(mappedBy = "notaFiscal", fetch = FetchType.LAZY,
cascade = {CascadeType.ALL},
orphanRemoval = true)
private List<NotaFiscalDocRef> listaDocRef;
@OneToMany(mappedBy = "notaFiscal", fetch = FetchType.LAZY,
cascade = {CascadeType.ALL},
orphanRemoval = true)
private List<NotaFiscalProcRef> listaProcRef;
//-----------------------------------------------------
//GRUPO DE CAMPO DE USO LIVRE
//-----------------------------------------------------
@OneToMany(mappedBy = "notaFiscal", fetch = FetchType.LAZY,
cascade = {javax.persistence.CascadeType.ALL},
orphanRemoval = true)
private List<NotaFiscalObsCont> listaObsCont;
@OneToMany(mappedBy = "notaFiscal", fetch = FetchType.LAZY,
orphanRemoval = true,
cascade = {CascadeType.ALL})
private List<NotaFiscalVeiculo> veiculos;
@OneToMany(mappedBy = "notaFiscal", fetch = FetchType.LAZY,
orphanRemoval = true,
cascade = {CascadeType.ALL})
private List<NotaFiscalVolumes> volumes;
@OneToMany(mappedBy = "notaFiscal", fetch = FetchType.LAZY,
cascade = {CascadeType.ALL},
orphanRemoval = true)
private List<NotaFiscalEvento> eventos;
@ElementCollection(fetch = FetchType.LAZY)
@CollectionTable(name = "notas_fiscais_email", joinColumns=@JoinColumn(name="nota_fiscal_id"))
private List<NotaFiscalEmail> listaEmail;
@ElementCollection(fetch = FetchType.LAZY)
@Column(name = "documento", length = 20, nullable = false)
@CollectionTable(name = "notas_fiscais_autxml", joinColumns=@JoinColumn(name="nota_fiscal_id"))
private List<String> listaAutXml;
Method that loads by id:
private NotaFiscal loadLazy(Long id) {
try {
String sql = "select o from NotaFiscal as o "
+ "left outer join o.listaEmail le "
+ "left outer join o.listaAutXml la "
+ "left outer join o.pagamentos p "
+ "left outer join o.duplicatas du "
+ "left outer join o.itens i "
+ "left outer join o.listaDocRef ldr "
+ "left outer join o.listaProcRef lpr "
+ "left outer join o.listaObsCont obs "
+ "left outer join o.eventos eve "
+ "left outer join o.volumes volumes "
+ "left outer join o.veiculos vei "
+ "where o.id = :id ";
Query query = getEntityManager().createQuery(sql);
query.setParameter("id", id);
return (NotaFiscal) query.getSingleResult();
} catch (Exception e) {
CriareLog.log(e);
return null;
}
}
Method in which the error occurs at the time of the list request.
public DataModel<NotaFiscalEmail> getEmailsDM() {
if (emailsDM == null) {
if (this.getBean().getListaEmail() == null) {
this.getBean().setListaEmail(new ArrayList<NotaFiscalEmail>());
}
// O erro ocorre exatamente nesta linha.
emailsDM = new ListDataModel<NotaFiscalEmail>(this.getBean().getListaEmail());
}
return emailsDM;
}
If you need anything else, tell me I’ll post it here. I appreciate all your help. Hugs
Good afternoon. Great explanation, when I’m in trouble I always try to research where things come from and why they really work to better understand them. Therefore, I ended up checking that I should use Join fetch, however after updating the load search to Join fetch I have the following problem: javax.persistence.Persistenceexception: org.hibernate.Loader.Multiplebagfetchexception: cannot fetch simultaneously Multiple bags. I’m already looking for the solution, but I’m also struggling! I really appreciate your help!
– Gilvan André
@Gilvanandré The problem is that it is not possible to fetch from multiple lists at the same time, because this is impossible via SQL. I guess you’ll have to use another alternative.
– utluiz
Man, what a headache this! I wouldn’t want to use Opensessioninview. My biggest problem is that I would need to optimize searches/reports, which due to the use of EAGER is too slow. Going to use Lazy, the research works perfectly, however I end up suffering from other problems! Anyway thank you so much for the reply, sensational! My congratulations!
– Gilvan André
@Gilvanandré Another thing you can do is to assemble each necessary object or list in your hand instead of composing a "monster object" at once. I understand your headache, which is why I’ve been avoiding JPA to the fullest. There just comes a time when the facilities don’t make up for the problems it brings.
– utluiz
Yes, our application is becoming large. And for some time we are already thinking about "abandoning" JPA. Even trying to use it the best, sometimes it gives more work than not using it!
– Gilvan André
@Gilvanandré So it is. Another thing you can try to do in these cases is to use Activate queries when necessary. But you still won’t be able to bring all that data at once.
– utluiz
@Gilvanandré The problem is using JPA the wrong way and not JPA itself. Write queries for reports instead of using the entity’s API to rescue collections through the root entity. It doesn’t have to be Native query, it can be HQL and you still have the ability to use business terms instead of field and table names. Just write down the queries you need, as many as you need, instead of waiting for automatic loading of child objects. Deliver the result of these queries into relevant data structures to the report instead of into collections of business objects.
– Caffé
@Caffé For reports I use this structure that you put, the question here is not for use in reports, but rather to use it in a CRUD. Since this CRUD is in JSF. Ported when closing the section (for example: submitting the page), I no longer have access to the variables that are Lazy. My solution would be to keep the session open, but it’s the last solution I want to use. For now we are using EAGER even, but studies continue to try to find a more efficient solution.
– Gilvan André
Another option we are studying to use is the Dtos, as the friend said when answering the question. This is also not out of the question, and may also be the way to solve the problem.
– Gilvan André
@Gilvanandré You wrote reports in your comment. Yes, in my comment (data structures) I’m agreeing with the utluiz Dtos option - it serves for reports and also for presentation layer manipulation.
– Caffé
@Caffé A yes... no comentário sim! : D
– Gilvan André