2011-06-01 41 views
1

我有型“文件夹”的对象之间一个非常简单的父 - /子关系,它看起来像这样:休眠删除后了Session.update(父)子对象

  • 一个文件夹可以有0-1父文件夹。
  • 一个文件夹可以有0-n个子文件夹 (子文件夹)。

所以,基本上,Java类文件夹的简化版本是这样的:

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(); 
    } 

} 

我简单的测试层次结构是这样的:

folder1 
    folder2 
- folder3 
    subfolder3-1 

使用Hibernate,我呼吁:

session.update(folder1); 
session.update(folder2); 
session.update(folder3); 

前两个调用成功。

最后一次对folder3的调用不会引发异常,但它会从folder3的内部set“childFolders”中删除子文件夹3-1。 这意味着,folder3.childFolders.size() = 0尽管在最后一次更新呼叫之前是1。 重要提示:在数据库中,文件夹“subfolder3-1”仍然存在!

这怎么可能?

这里是我的映射文件:

<?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> 

     <many-to-one name="parentFolder" column="PARENT_FOLDER_ID" /> 

     <property name="path" column="FOLDER_PATH" /> 
    </class> 
</hibernate-mapping> 
+0

'test.Folder'中的'equals()'和'hashcode()'方法是什么样的? – 2011-06-01 20:34:06

+0

@matt b我在原文中加了两个方法 – Timo 2011-06-01 21:17:37

回答

0

我增加了一些调试代码,我终于找到了解决办法:直接在session.update(folder3)电话之前,我有一个小小的隐藏folder.childFolders.clear()调用这显然造成了问题,所以这个问题也没有与Hibernate有关。只是我的愚蠢。 对不起,每个人都很烦恼,并且非常感谢您的帮助!

0

我认为这个问题是在逆=“true”属性:inverse属性不会被保存。

+0

Hm,设置inverse =“false”没有解决问题。除此之外:调用session.save(folder3)完美地工作。 – Timo 2011-06-01 21:31:41

0

确保您在java世界中正确建立链接。

folder3.getChildFolders().add(subfolder3); 
    subfolder3.setParent(folder3); 
    session.persist(folder3); //cascade here will save subfolder3 

Here is the hibernate documentation.

+0

在我调用上面发布的session.update(..)方法之前,所有文件夹都已经存在了!所以,我在永久性文件夹上调用session.update(..)。为了将文件夹插入数据库(第一次),我使用session.save。(folder3)(完美工作)而不是session.persist(folder3)。那是错的吗? – Timo 2011-06-01 22:13:03

+0

在最初将文件夹插入到数据库中的代码中,是否还要将该文件夹添加到父项(如上面的@zmf所示)? – RMorrisey 2011-06-01 22:26:31

+0

@Rorrisey是的,我喜欢。我还在'session.update(folder3)'调用之前和之后一次打印树(包括父和父的名称)。在'session.update(folder3)'之前,'一切都是它应该的(子文件夹3-1有一个id和一个对它的父亲的引用)。更新调用后,子文件夹3-1不见了。 – Timo 2011-06-02 00:22:02