I have a very simple parent-/child relationship between objects of type "Folder", which looks like this:
- A folder can have 0-1 parent folders.
- A folder can have 0-n child folders (subfolders).
So, basically, a simplified version of the Java class Folder looks like this:
public class Folder{
long id;
Set<Folder> childFolders;
Folder parentFolder;
String path;
// Getter, setter and other (for this question)
// not relevant properties omitted
public boolean equals(Object obj){
if (obj == null) return false;
if (obj == this) return true;
if (obj instanceof Folder){
Folder folder = (Folder)obj;
return folder.getPath().equals(getPath());
}
return false;
}
public int hashCode(){
return getPath().hashCode();
}
}
My simple test hierarchy looks like this:
folder1
folder2
- folder3
subfolder3-1
Using Hibernate, I call:
session.update(folder1);
session.update(folder2);
session.update(folder3);
The first two calls succeed.
The last call for folder3 throws no exception BUT it removes subfolder3-1 from the internal set "childFolders" of folder3.
That means, folder3.childFolders.size() = 0
although it was 1 before the last update call.
Important: In the database, folder "subfolder3-1" still exists!
How can that be?
Here is my mapping file:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="test.Folder" table="FOLDERS">
<id name="id" type="long" access="field">
<column name="FOLDER_ID" />
<generator class="native" />
</id>
<set name="childFolders" table="FOLDERS" inverse="true" cascade="save-update">
<key column="PARENT_FOLDER_ID"></key>
<one-to-many class="test.Folder" />
</set>
&开发者_JAVA百科lt;many-to-one name="parentFolder" column="PARENT_FOLDER_ID" />
<property name="path" column="FOLDER_PATH" />
</class>
</hibernate-mapping>
I think that the issue is in the inverse="true" attribute: inverse attributes are not saved.
Make sure you're establishing the link properly in the java world.
folder3.getChildFolders().add(subfolder3);
subfolder3.setParent(folder3);
session.persist(folder3); //cascade here will save subfolder3
Here is the hibernate documentation.
I added some more debug code and I finally found the solution: Directly before the session.update(folder3)
call, I had a tiny hidden folder.childFolders.clear()
call which obviously caused the issue, so the problem didn't have something to do with Hibernate at all. Just with my stupidness.
Sorry everyone for bothering and thanks a lot for the help!
精彩评论