I know there are loads of entries about this topic. I have already read all of them searching for the problem I am facing.

I have a class/table with a self-reference. This is the Class

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
}

And here you can see the hbm.xml file:

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

So far everything is fine. But I must have an error somewhere because, when I am running this unit test

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

I added the last two lines in order to show you the problem I am facing right now:

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]

Both parent and child are the same! I don't really understand the problem here. When I retrieve the child through a query the result is correct but when I get the child through getChild() there's not query to retrieve the its childs.

Have you any idea? Any clue? I do not see the light at the end of the tunnel here :-/

Thanks a lot in advance!

有帮助吗?

解决方案

I finally have realized what the problem was! Well, there was couple of problems.

First, there was no parent_id field in neither the DB nor the class. Second, there was no exception because I activated inverse property to the set.

The combination of both issues was the problem.

Below, I post the working solution.

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>

I hope this is helpful for someone in the future. This is the first time I post a self-solution :)

其他提示

Take a shot using the code below:

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

from this

your issue will be resolved by properly defining cascading depedencies or by saving the referenced entities before saving the entity that references. Defining cascading is really tricky to get right because of all the subtle variations in how they are used.

cascade="delete"

check the options all|none|save-update|delete|all-delete-orphan

session.save(child); instead of this try cascade="all" and session.save(parent) so that all child objects will be saved with parent.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top