Hibernate自我引用父子

时间:2014-03-08 18:33:39

标签: java sql spring hibernate one-to-many

我知道有很多关于这个主题的条目。我已经阅读了所有他们正在寻找我面临的问题。

我有一个带有自引用的类/表。这是班级

public class Comment {

    private Integer id;
    private Comment parent;
    private Issue   issue;
    private User    author;
    private String  body;
    private Date    created;
    private Date    updated;

    private Set<Comment> childs;

    // All setters and getters
}

在这里你可以看到hbm.xml文件:

<hibernate-mapping>
 <class name="Comment" table="COMMENTS">

  <id name="id" type="java.lang.Integer">
   <column name="ID"/>
   <generator class="native"/>
  </id>

  <many-to-one cascade="all"
   class="Comment" fetch="join" name="parent">
   <column name="PARENT" not-null="false"/>
  </many-to-one>

  <many-to-one class="Issue"
   fetch="join" name="issue">
   <column name="ISSUE" not-null="true"/>
  </many-to-one>

  <many-to-one class="User"
   fetch="join" name="author">
   <column name="AUTHOR" not-null="true"/>
  </many-to-one>

  <property generated="never" lazy="false" name="body" type="java.lang.String">
   <column name="BODY" not-null="true"/>
  </property>

  <property generated="never" lazy="false" name="created" type="java.util.Date">
   <column name="CREATED"/>
  </property>

  <property generated="never" lazy="false" name="updated" type="java.util.Date">
   <column name="UPDATED"/>

  </property>
  <set cascade="delete" fetch="select" inverse="true" lazy="true"
   name="childs" sort="unsorted" table="COMMENTS">
   <key>
    <column name="ID" not-null="true"/>
   </key>
   <one-to-many class="Comment"/>
  </set>

 </class>

</hibernate-mapping>

到目前为止一切都很好。但是我必须在某个地方出错,因为当我运行这个单元测试时

Session session = sessionFactory.getCurrentSession();

User user = new User("loginName", "password", "firstName", "lastName", "eMail");
session.save(user);
session.flush();
session.clear();

Issue issue = new Issue();
session.save(issue);
session.flush();
session.clear();

Comment parent = new Comment(issue, user, "body_parent");
session.save(parent);

Comment child = new Comment(issue, user, "body_child_1");
child.setParent(parent);
parent.getChilds().add(child);
session.save(child);
session.flush();
session.clear();

parent = (Comment) session.createQuery("from Comment comment where comment.body='body_parent'").uniqueResult();

System.out.println(parent);
System.out.println(parent.getChilds().iterator().next());

我添加了最后两行,以便向您展示我现在面临的问题:

COMMENT = [id=1, parentId=<root>, issueId=1, authorId=1, body=body_parent, created=2014-03-08 19:28:54.832, updated=2014-03-08 19:28:54.832, numChilds=1]
COMMENT = [id=1, parentId=<root>, issueId=1, authorId=1, body=body_parent, created=2014-03-08 19:28:54.832, updated=2014-03-08 19:28:54.832, numChilds=1]

父母和孩子都是一样的!我真的不明白这里的问题。 当我通过查询检索孩子时,结果是正确的,但是当我通过getChild()获取孩子时,没有查询来检索孩子。

你有什么想法吗?任何线索?我在这里看不到隧道尽头的灯光: - /

提前多多感谢!

3 个答案:

答案 0 :(得分:2)

我终于意识到问题是什么!好吧,有几个问题。

首先,DB和类中都没有parent_id字段。 其次,没有例外,因为我将inverse属性激活到了集合。

两个问题的结合是问题。

下面,我发布工作解决方案。

<强> Comment.java

public class Comment {
    private Integer      id;
    private Integer      parentId; // Parent ID was missing
    private Issue        issue;
    private User         author;
    private String       body;
    private Date         created;
    private Date         updated;

    private Comment      parent; // Reference to parent though parentId
    private Set<Comment> childs = new HashSet<Comment>(0);


    protected Comment () {

    }

   // All setters and getters
}

<强> Comment.hbm.xml

<hibernate-mapping>
 <class name="es.kazbeel.geckobugtracker.model.Comment" table="COMMENTS">

  <id name="id" type="java.lang.Integer">
   <column name="ID"/>
   <generator class="native"/>
  </id>

  <property name="parentId" type="java.lang.Integer" update="false" insert="false" column="PARENT_ID" />

  <many-to-one class="es.kazbeel.geckobugtracker.model.Issue"
   fetch="join" name="issue">
   <column name="ISSUE"/>
  </many-to-one>

  <many-to-one class="es.kazbeel.geckobugtracker.model.User"
   fetch="join" name="author">
   <column name="AUTHOR"/>
  </many-to-one>

  <property generated="never" lazy="false" name="body" type="java.lang.String">
   <column name="BODY"/>
  </property>

  <property generated="never" lazy="false" name="created" type="java.util.Date">
   <column name="CREATED"/>
  </property>

  <property generated="never" lazy="false" name="updated" type="java.util.Date">
   <column name="UPDATED"/>
  </property>

  <many-to-one name="parent" class="es.kazbeel.geckobugtracker.model.Comment" column="PARENT_ID" not-null="false" />

  <set name="childs" table="COMMENTS"  lazy="false" cascade="all-delete-orphan" inverse="false">
   <key column="PARENT_ID" />
   <one-to-many class="es.kazbeel.geckobugtracker.model.Comment"/>
  </set>

 </class>
</hibernate-mapping>

我希望这有助于将来的某些人。这是我第一次发布自我解决方案:)

答案 1 :(得分:1)

使用以下代码拍摄:

Comment parent = new Comment(issue, user, "body_parent");
Comment child = new Comment(issue, user, "body_child_1");
child.setParent(parent);
parent.getChilds().add(child);
session.save(parent);
session.flush();
session.clear();

答案 2 :(得分:1)

来自this

  

通过正确定义级联依赖关系可以解决您的问题   或者在保存实体之前保存引用的实体   引用。定义级联是非常棘手的,因为   它们如何被使用的所有微妙变化。

级联= “删除”

检查选项all | none | save-update | delete | all-delete-orphan

session.save(child);代替此try cascade="all" and session.save(parent),以便所有子对象都将与父级一起保存。