I am facing a strange issue with JPA CascadeType.REFRESH attribute. I have a simple parent-child relationship in which in parent domain object(LineEquipmentFormat) I have added the cascade attributes like below
OneToMany(cascade = { CascadeType.REFRESH, CascadeType.MERGE, CascadeType.PERSIST,
CascadeType.REMOVE}, mappedBy = "lineEquipmentFormat")
public List<LineEquipmentFormatDivision> getLineEquipmentFormatDivisions() {
return lineEquipmentFormatDivisions;
}
But when I fetch the parent LineEquipmentFormat object from DB, I do not get the list of LineEquipmentFormatDivisions.
Error I am getting is
17:46:34,251 ERROR [LazyInitializationException] failed to lazily initialize a collection of role: LineEquipmentFormat.lineEquipmentFormatDivisions, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: LineEquipmentFormat.lineEquipmentFormatDivisions, no session or session was closed
at 开发者_运维技巧org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:380)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:372)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:365)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:108)
at org.hibernate.collection.PersistentBag.toString(PersistentBag.java:506)
I am using Jboos 5.1 and Oracle 10G.
Please provide more inputs on possible root cause of this error.
Thanks
When you define the cascade type as refresh, that means when the entityManager.refresh() is called on the parent LineEquipmentFormat, it will be also called on the child LineEquipmentFormatDivisions. However, the error that you are getting indicates that you tried to lazily initialize the collection while the session is closed. If you need this collection after the session is closed, you need to fetch them eagerly by setting the fetchType.
I have added the cascade attributes like below (...) But when I fetch the parent LineEquipmentFormat object from DB, I do not get the list of LineEquipmentFormatDivisions.
Cascading operations has little to do with EAGER or LAZY loading and in your case, the error you are getting (the infamous LazyInitializationException
) means that you are trying to access a lazy association but that the session has already been closed (so Hibernate can't load it).
To avoid this "problem", either:
- eager load the association using the
fetchType
attribute (that's IMO putting "lipstick on the pig" if you don't need the association in most scenario) use a
FETCH JOIN
for this particular use case to fetch the association while executing queries, eg:SELECT f FROM LineEquipmentFormat f LEFT JOIN FETCH f.lineEquipmentFormatDivisions WHERE f.id = 1
use the Open EntityManager In View pattern (in a MVC context) to open the entity manager when a request comes in and keep it open until the request has been handled (Spring has a Serlvet filter or an Interceptor implementing this pattern).
Thanks for your comments.
Here is how we have finally implemented it.
While fetching the "LineEquipmentFormat" parent object we have added following additional code.
LineEquipmentFormat lef = entityManager.find(LineEquipmentFormat.class, sysId); if (lef != null && lef.getLineEquipmentFormatDivisions() != null) { lef.getLineEquipmentFormatDivisions().size(); }
return lef;Now if we can fetch the child list from this parent object.
精彩评论