-->
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.  [ 6 posts ] 
Author Message
 Post subject: Basic question and problem with saving one-to-many assoc.
PostPosted: Sat Jan 30, 2010 1:08 pm 
Newbie

Joined: Wed Jan 06, 2010 9:09 pm
Posts: 14
Hi All,

I've got a simple test case which is not working and I'd like to understand why.
The parent class is a TravelTimeSegment, it has amongst other members a set of TravelTimeGPSPoints in a one-to-many association. When creating a new TravelTimeSegment object and a new associated TravelTimeGPSPoints I'd like both objects to be saved and the correct foreign key in the TravelTimeGPSPoints set to point back to the parent TravelTimeSegment. My simple unit test case is not working however. Can anyone see what's wrong with the code and config. below? I'd like to understand why this doesn't work before moving away from the default settings for cascading saves etc. Note I had to auto generate the hibernate config. files from an existing schema.

Thanks a great deal,
Fred,

The parent object:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Jan 18, 2010 3:23:48 PM by Hibernate Tools 3.2.0.beta8 -->
<hibernate-mapping>
    <class name="com.xxx.orm.TravelTimeSegment" table="TravelTimeSegment" catalog="xyz">
        <comment>
        </comment>

        <id name="id" type="long">
            <column name="id" />

            <generator class="assigned" />
        </id>

        <property name="listenPort" type="int">
            <column name="listenPort" not-null="true">
                <comment>
                </comment>
            </column>
        </property>

        <property name="isDead" type="byte">
            <column name="isDead" not-null="true">
                <comment>
                </comment>
            </column>
        </property>

        <property name="modifyTime" type="timestamp">
            <column name="modifyTime" length="19" not-null="true">
                <comment>
                </comment>
            </column>
        </property>
       
 
        <set name="travelTimeGPSPoints" table="TravelTimeGPSPoints" lazy="false">
            <key column="travelTimeSegmentId"/>
            <one-to-many class="com.xxx.orm.TravelTimeGPSPoints"/>
        </set>

    </class>
</hibernate-mapping>


The child object:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Jan 18, 2010 3:23:48 PM by Hibernate Tools 3.2.0.beta8 -->
<hibernate-mapping>
    <class name="com.xxx.orm.TravelTimeGPSPoints" table="TravelTimeGPSPoints" catalog="xyz">
        <comment>
        </comment>

        <composite-id name="id" class="com.xxx.orm.TravelTimeGPSPointsId">
            <key-property name="travelTimeSegmentId" type="long">
                <column name="travelTimeSegmentId" />
            </key-property>

            <key-property name="latitude" type="double">
                <column name="latitude" precision="22" scale="0" />
            </key-property>

            <key-property name="longitude" type="double">
                <column name="longitude" precision="22" scale="0" />
            </key-property>

            <key-property name="sequenceNumber" type="int">
                <column name="sequenceNumber" />
            </key-property>
        </composite-id>
    </class>
</hibernate-mapping>


The java code:
Code:
public class TestHibernate {
   
   @SuppressWarnings("unchecked")
   @Test
   public void testAddSegment() throws Exception {
      try {
            HibernateUtil.getSessionFactory().getCurrentSession().beginTransaction();
           
            // want to create a new segment and add one GPS point to it
           final TravelTimeSegment seg = new TravelTimeSegment(0, 10000, (byte)0, new Date()); 
           final TravelTimeGPSPoints p1 = new TravelTimeGPSPoints(new TravelTimeGPSPointsId(0, 38.4, 119.4, 0));           
           final Set<TravelTimeGPSPoints> gpsPoints = seg.getTravelTimeGPSPoints();
           gpsPoints.add(p1);
           
           // would like to save the segment here and have it automatically save the gps point and set the association
           // of gps point to the owner segment
           HibernateUtil.getSessionFactory().getCurrentSession().save(seg);
           //HibernateUtil.getSessionFactory().getCurrentSession().save(p1);
            HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().commit();
        }
        catch (Exception ex) {
            HibernateUtil.getSessionFactory().getCurrentSession().getTransaction().rollback();
            throw ex;
        }       
   }
}


Top
 Profile  
 
 Post subject: Re: Basic question and problem with saving one-to-many assoc.
PostPosted: Mon Feb 01, 2010 3:46 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Quote:
I've got a simple test case which is not working


Now that you have posted the test case... can you also tell us what the problem is? What happens when you run it?


Top
 Profile  
 
 Post subject: Re: Basic question and problem with saving one-to-many assoc.
PostPosted: Mon Feb 01, 2010 4:25 pm 
Newbie

Joined: Wed Jan 06, 2010 9:09 pm
Posts: 14
Sure, sorry about that, must have gotten distracted with the details.

When I create a new traveltime segment, create a new gps point, add the gps point to the set of points owned by the new travel time segment object, save both the segment and gps point, they are both saved to the database OK, but the foreign id key of the gps point does not point back to the parent travel time segment, i.e. the two are not associated.

I'd like to get my configuration such that I can create a parent object, add a new child to the set, then just save the parent and have it auto save the child AND have the relationship between the two also saved?

Code:
                        final TravelTimeSegment seg = new TravelTimeSegment(0, 10000, 1, 10, 0, 0, form.getSegmentName(), form.getClassification(), (byte)0, new Date()); 
                        final Set<TravelTimeGPSPoints> gpsPoints = seg.getTravelTimeGPSPoints();
                        TravelTimeGPSPoints p = new TravelTimeGPSPoints(new TravelTimeGPSPointsId(0, form.getX1(), form.getY1(), 0));
                        gpsPoints.add(p);
                        
                        // TODO : foreign key of new TravelTimeGPSPoints not pointing back to owner TravelTimeSegment successfully
                        HibernateUtil.getSessionFactory().getCurrentSession().save(seg);
                        HibernateUtil.getSessionFactory().getCurrentSession().save(p);


Top
 Profile  
 
 Post subject: Re: Basic question and problem with saving one-to-many assoc.
PostPosted: Tue Feb 02, 2010 10:45 am 
Newbie

Joined: Tue Feb 02, 2010 10:37 am
Posts: 13
Hi fredbasset,
You need to checkout two things:
i) Hibernate doesn't take care of setting two ends of the association ; it has to be implemented in code
child.setParent(Parent) --> this piece is missing in your snippet.
ii) cascade has to be set in the collections mapping as "all" so that children items are saved along with parent. (This is not relevant to your issue as you are saving both child and parent with explicit calls


Top
 Profile  
 
 Post subject: Re: Basic question and problem with saving one-to-many assoc.
PostPosted: Tue Feb 02, 2010 1:39 pm 
Newbie

Joined: Wed Jan 06, 2010 9:09 pm
Posts: 14
Thanks for the reply vijaybangy. I did not have an explicit mapping of the child back to the parent in the original child config file:
Code:
<hibernate-mapping>
    <class name="com.xxx.orm.TravelTimeGPSPoints" table="TravelTimeGPSPoints" catalog="snaps">
        <comment>
        </comment>

        <composite-id name="id" class="com.xxx.orm.TravelTimeGPSPointsId">
            <key-property name="travelTimeSegmentId" type="long">
                <column name="travelTimeSegmentId" />
            </key-property>

            <key-property name="latitude" type="double">
                <column name="latitude" precision="22" scale="0" />
            </key-property>

            <key-property name="longitude" type="double">
                <column name="longitude" precision="22" scale="0" />
            </key-property>

            <key-property name="sequenceNumber" type="int">
                <column name="sequenceNumber" />
            </key-property>
        </composite-id>
    </class>
</hibernate-mapping>


I then tried adding a many-one relationship in the child:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated Jan 18, 2010 3:23:48 PM by Hibernate Tools 3.2.0.beta8 -->
<hibernate-mapping>
    <class name="com.xxx.orm.TravelTimeGPSPoints" table="TravelTimeGPSPoints" catalog="snaps">
        <comment>
        </comment>

        <composite-id name="id" class="com.xxx.orm.TravelTimeGPSPointsId">
            <key-property name="travelTimeSegmentId" type="long">
                <column name="travelTimeSegmentId" />
            </key-property>

            <key-property name="latitude" type="double">
                <column name="latitude" precision="22" scale="0" />
            </key-property>

            <key-property name="longitude" type="double">
                <column name="longitude" precision="22" scale="0" />
            </key-property>

            <key-property name="sequenceNumber" type="int">
                <column name="sequenceNumber" />
            </key-property>
        </composite-id>
       
        <many-to-one name="segment" column="travelTimeSegmentId" class="com.xxx.orm.TravelTimeSegment">
        </many-to-one>
    </class>
</hibernate-mapping>


and changed my code for setting the new parent and child to:
Code:
           final TravelTimeSegment seg = new TravelTimeSegment(0, 10000, 1, 10, 0, 0, "classif", "unit test segment", (byte)0, new Date(), new HashSet<TravelTimeLink>(), new HashSet<TravelTimeGPSPoints>()); 
           final TravelTimeGPSPoints p1 = new TravelTimeGPSPoints(new TravelTimeGPSPointsId(0, 38.4, 119.4, 0));           
           final Set<TravelTimeGPSPoints> gpsPoints = seg.getTravelTimeGPSPoints();
           gpsPoints.add(p1);
           p1.setSegment(seg);
           
           // would like to save the segment here and have it automatically save the gps point and set the association
           // of gps point to the owner segment
           HibernateUtil.getSessionFactory().getCurrentSession().save(seg);
           HibernateUtil.getSessionFactory().getCurrentSession().save(p1);


I then get a hibernate exception, which looks like it now thinks there are 2 foreign keys there. All I want to do is have the one foreign key in the child as I have to use an existing schema, and have Hibernate understand that the child is associated to the parent. Can anyone PLEASE help? I also included the legacy tables below the stack trace:

java.lang.ExceptionInInitializerError
at com.xxx.HibernateUtil.<clinit>(HibernateUtil.java:35)
at com.xxx.orm.TestHibernate.testAddSegment(TestHibernate.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: com.xxx.orm.TravelTimeGPSPoints column: travelTimeSegmentId (should be mapped with insert="false" update="false")
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:652)
at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:674)
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:696)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:450)
at org.hibernate.mapping.RootClass.validate(RootClass.java:192)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1102)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1287)
at com.xxx.HibernateUtil.<clinit>(HibernateUtil.java:27)
... 23 more


The parent:
Code:
mysql> describe TravelTimeLink;
+---------------------+---------------------+------+-----+---------------------+----------------+
| Field               | Type                | Null | Key | Default             | Extra          |
+---------------------+---------------------+------+-----+---------------------+----------------+
| id                  | bigint(20) unsigned | NO   | PRI | NULL                | auto_increment |
| listenPort          | int(10) unsigned    | NO   |     | NULL                |                |
| linkCapacity        | int(10) unsigned    | NO   |     | NULL                |                |
| maxTravelTime       | int(10) unsigned    | NO   |     | NULL                |                |
| maxLatency          | int(10) unsigned    | NO   |     | NULL                |                |
| linkName            | varchar(64)         | NO   |     | NULL                |                |
| isMIMO              | tinyint(3) unsigned | NO   |     | NULL                |                |
| ARSEServerNodeId    | bigint(20) unsigned | NO   | MUL | NULL                |                |
| travelTimeSegmentId | bigint(20) unsigned | NO   | MUL | NULL                |                |
| isDead              | tinyint(3) unsigned | NO   |     | NULL                |                |
| modifyTime          | timestamp           | NO   |     | 0000-00-00 00:00:00 |                |
+---------------------+---------------------+------+-----+---------------------+----------------+


The child:
Code:
mysql> describe TravelTimeGPSPoints;
+---------------------+---------------------+------+-----+---------+-------+
| Field               | Type                | Null | Key | Default | Extra |
+---------------------+---------------------+------+-----+---------+-------+
| travelTimeSegmentId | bigint(20) unsigned | NO   | MUL | NULL    |       |
| latitude            | double              | NO   |     | NULL    |       |
| longitude           | double              | NO   |     | NULL    |       |
| sequenceNumber      | int(10) unsigned    | NO   |     | NULL    |       |
+---------------------+---------------------+------+-----+---------+-------+


Top
 Profile  
 
 Post subject: Re: Basic question and problem with saving one-to-many assoc.
PostPosted: Tue Feb 02, 2010 5:36 pm 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
There is a good example about various kinds of parent/child mappings and also some recommendations in the Hibernate documentation. See http://docs.jboss.org/hibernate/stable/ ... child.html

The problem you are having with the mapping is that you have mapped the travelTimeSegmentId column twice. Once with <key-property> and once with <many-to-one>. You should get rid of the <many-to-one> and use <key-many-to-one> instead of <key-property>. There are a few example in the documentation: http://docs.jboss.org/hibernate/stable/ ... ompositeid


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 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.