-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: simple tree structure node children problem
PostPosted: Sun May 22, 2011 1:44 pm 
Newbie

Joined: Sun May 22, 2011 1:29 pm
Posts: 1
I'm very confused by the behavior I'm seeing. I must be doing something wrong, but the code I have seems very similar to other examples I've seen in my googling (some from this forum though I neglected to keep around the links).

I'm just trying to represent some simple hierarchical data. This was part of a more complicated system, but I pulled it out and tried to simplify it as much as possible and still can't get it to work, so any help is appreciated.

I've copied and pasted three files. First is my Java class where I'm setting up my mappings using annotations. Second is a simple Spring file where I'm configuring a basic in-memory database using HSQL, setting up the session factory and transaction manger, etc, and third is a JUnit test that is failing.

It is the final assert in the JUnit test that is failing, basically no children are being retrieved, the children list has size 0. The manual query I do to find any nodes with the parent behaves as expected, I get back the single child node.

Ideas?

Oh, and I am using hibernate 3.6.4...

Code:
@Entity
public class Node {

   private Long id;
   private Node parent;
   private List<Node> children = new ArrayList<Node>();
   
   @Id
   @GeneratedValue
   public Long getId() {
      return id;
   }
   public void setId(Long id) {
      this.id = id;
   }
   @ManyToOne
   public Node getParent() {
      return parent;
   }
   public void setParent(Node parent) {
      this.parent = parent;
   }
   @OneToMany(mappedBy="parent")
   public List<Node> getChildren() {
      return children;
   }
   public void setChildren(List<Node> children) {
      this.children = children;
   }
}



Code:
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
   xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
   xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
      http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

   <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
      destroy-method="close" p:driverClassName="org.hsqldb.jdbcDriver"
      p:url="jdbc:hsqldb:mem:test" p:username="sa" p:password=""
      p:testOnBorrow="true" />

   <bean id="sessionFactory"
      class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"
      p:dataSource-ref="dataSource">
      <property name="hibernateProperties">
         <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.generate_statistics">true</prop>
            <prop key="hibernate.hbm2ddl.auto">create-drop</prop>         
         </props>
      </property>
      <property name="eventListeners">
         <map>
            <entry key="merge">
               <bean
                  class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener" />
            </entry>
         </map>
      </property>
      <property name="packagesToScan" value="com.entitytest" />
   </bean>

   <tx:annotation-driven transaction-manager="transactionManager" />

   <bean id="transactionManager"
      class="org.springframework.orm.hibernate3.HibernateTransactionManager">
      <property name="sessionFactory" ref="sessionFactory"/>
   </bean>
</beans>



Code:
package com.entitytest;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:/app-context-hierarchy-test.xml"})
@Transactional
public class HierarchyTest {

   @Autowired
   private SessionFactory sessionFactory;
   
   @Test
   public void test() throws Exception {
      Node parent = new Node();
      sessionFactory.getCurrentSession().merge(parent);
      System.out.println("parent id: " + parent.getId());
      
      Node child = new Node();
      child.setParent(parent);
      sessionFactory.getCurrentSession().merge(child);
      
      int manualCount = sessionFactory.getCurrentSession().createCriteria(Node.class)
         .add(Restrictions.eq("parent", parent)).list().size();
      assertEquals(1, manualCount);
      
      Node result = (Node)sessionFactory.getCurrentSession().load(
            Node.class, parent.getId());      
      assertNotNull(result.getChildren());
      assertEquals(1, result.getChildren().size());
            
   }

   public void setSessionFactory(SessionFactory sessionFactory) {
      this.sessionFactory = sessionFactory;
   }   
}


Top
 Profile  
 
 Post subject: Re: simple tree structure node children problem
PostPosted: Mon May 23, 2011 4:02 pm 
Beginner
Beginner

Joined: Mon Jul 28, 2008 4:36 pm
Posts: 24
Quote:
Code:
Node parent = new Node();
sessionFactory.getCurrentSession().merge(parent);


What the heck does merge() do? I've never used that. I always use save() for new objects.

After the save() I always end up doing:
Code:
hS.getTransaction().commit();
if (hS.isOpen()) { hS.close(); }
hS = HibernateUtil.getSessionFactory().getCurrentSession();
hS.beginTransaction();

Then I refresh the parent with the generated ID:
Code:
parent = (Node) hS.get(Node.class, parent);

Only after that do I:
Code:
child.setParent(parent);


The only way I know of to save the parent and child in the same Hibernate session is to map the association with cascade="save-update" in the .hbm.xml file, and I don't want Hibernate to dirty-check most of my object graph before every single save. If you know of some other good way, or a really compelling reason to use cascade="save-update" by default, I'm very interested to hear, because the whole opening and closing session thing gets tiring, especially when you have to re-initialize things that you already queried in previous sessions.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.