Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp
Hibernate version:
3.2
Mapping documents:
10+
Code between sessionFactory.openSession() and session.close():
using Filter from Open Session In View pattern.
Full stack trace of any exception that occurs:
Code:
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: model.Unit.groups, no session or session was closed
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:358)
at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:350)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:343)
at org.hibernate.collection.PersistentSet.remove(PersistentSet.java:213)
at gui.page.unit.Units.removeChildGroupsAssociations(Units.java:229)
at
gui.page.unit.Units.deleteSelectedGroup(Units.java:207)
...
Name and version of the database you are using:Firebird2
I have a problem with session and detached objects, searched the forums but couldn't find a solution.
I have a many-to-many bidirectional association between Units and their UnitGroups mapped as a lazy loaded Set at both ends. Also groups can be arranged as a tree of groups (group can have childGroups and a parent) Lazy loading is needed here.
I'm trying to delete a group, hence I need to clear the association. This is were things get messy.
Here's the code for that:
Code:
public String deleteSelectedGroup() {
assert currentUnitGroup != null;
UnitGroup deletedGroup = currentUnitGroup;
UnitGroup orphanedUnitsGroup = deletedGroup.getParentGroup(); //new parent for orphaned units
if (orphanedUnitsGroup != null) //if we have a new parent for orphaned groups
{
List<Unit> orphanedUnits = getGroupUnitsRecursive(deletedGroup, new ArrayList<Unit>());
for (Unit unit : orphanedUnits) {
Set<UnitGroup> unitGroups = unit.getGroups();
unitGroups.add(orphanedUnitsGroup);
}
}
removeChildGroupsAssociations(deletedGroup); //removes all many-to-many group<>units association for deleted group and it's children
getSession().delete(deletedGroup);
currentUnitGroup = orphanedUnitsGroup;
return "";
}
/**
* This method goes through the group tree starting at a specific group node and removes ALL unit<>group associations it can find
* This is a necessary step when deleting a group.
*
* @param group
*/
private void removeChildGroupsAssociations(UnitGroup group) {
for (UnitGroup childGroup : group.getChildGroups()) {
removeChildGroupsAssociations(childGroup);
}
for (Unit unit : group.getUnits()) {
unit.getGroups().remove(group); //HERE'S THE PROBLEM
}
group.getUnits().clear();
}
I've commented the part throwing the exception. When I look at the debugger, I can see that deletedGroup.childGroups (a persistent set) has session=null; however the data is fetched eagerly before deletion somewhere else, so there's no problem viewing that collection at this point.
So deletedGroup appears to be detached from current session. The thing is, when I try to reattach it (using session.update or session.lock(..,LockMode.NONE) I get:
Code:
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [model.UnitGroup#35]
I also tried Session.merge(deletedGroup) but this appears to do nothing, the initial LazyInitializationException still popups.
So if deleteGroups is attached to the session, why it's persistentSet instance has session=null?
More impotantly, if it's connected, why units stored in the set are detached ?
The mappings:
UnitGroup
Code:
<!-- child groups and parent group -->
<set name="childGroups" table="UNIT_GROUPS" cascade="all-delete-orphan, lock" inverse="true">
<key column="PARENT_GROUP_ID"/>
<one-to-many class="model.UnitGroup" />
</set>
<many-to-one name="parentGroup"
class="model.UnitGroup" column="PARENT_GROUP_ID">
</many-to-one>
<!-- Units set -->
<set name="units"
cascade="save-update, lock"
inverse="true"
table="UNITS_GROUPS">
<key column="GROUP_ID"/>
<many-to-many class="model.Unit" column="UNIT_ID"/>
</set>
Unit:
Code:
<set name="groups"
table="UNITS_GROUPS"
cascade="save-update, lock">
<key column="UNIT_ID"/>
<many-to-many class="model.UnitGroup" column="GROUP_ID"/>
</set>
I'm lost :/
For now the solution is to get a "new" instance using findById dao method, but that's hardly a solution.