-->
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.  [ 3 posts ] 
Author Message
 Post subject: how to persist objects with circular references?
PostPosted: Tue Jul 21, 2009 11:13 am 
Newbie

Joined: Tue Jul 21, 2009 9:49 am
Posts: 3
Hi, I am assuming it is possible to persist objects with circular references as neither google nor the manual seem to say this is impossible (or perhaps I have been using the wrong search terms). If this is the case I believe it stems from a fairly fundamental misunderstanding of how to persist a simple single object reference and have this cascaded upon save.

The best way to explain is in the example below. I basically create a class of the form:

Code:
        public class A
        {
            public virtual int Id { get; set; }
            public virtual A Next { get; set; }
        }


and then create 2 objects of type A called a1,a2
I set it up so that they point to one another, e.g.
a1.Next = a2;
a2.Next = a1;

I would then like to create mappings so that when I save one, the other is automatically saved via cascade in such a manner that their Next members are preserved. I have not been able to do this. Could somebody please give me an example of a mapping that can do this?

So far I have tried creating a hbm.xml which uses a many-to-one mapping. This does not work as a1.Next is not saved in the database. (Out of desperation I tried a one-to-one mapping but this results in an even more nonsensical setup, creating a table with nothing but an Id column)

example below:

Code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using FluentNHibernate.Cfg;
using FluentNHibernate.Mapping;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;

namespace hibernate.experiment
{
    [TestFixture]
    public class CircularDemo
    {
        [Test]
        public void CircularTest()
        {
            var file = "circulardemo.db";
            if (File.Exists(file))
                File.Delete(file);

            Configuration c = new Configuration();
            c.Properties["dialect"] = "NHibernate.Dialect.SQLiteDialect";
            c.Properties["connection.provider"] = "NHibernate.Connection.DriverConnectionProvider";
            c.Properties["connection.driver_class"] = "NHibernate.Driver.SQLite20Driver";
            c.Properties["connection.connection_string"] = "Data Source=" + file + ";Version=3;";
            c.AddFile("hibernate.experiment.CircularDemo+A.hbm.xml");

            new SchemaExport(c).Create(true, true);

            var sFactory = c.BuildSessionFactory();

            using (var s = sFactory.OpenSession())
            {
                A a1 = new A();
                A a2 = new A();

                a1.Next = a2;
                a2.Next = a1;

                Assert.NotNull(a1.Next);
                Assert.NotNull(a2.Next);

                s.Save(a1);
            }

            using (var s = sFactory.OpenSession())
            {
                foreach (var a in s.CreateCriteria(typeof(A)).List<A>())
                    Assert.NotNull(a.Next);
            }
        }

        public class A
        {
            public virtual int Id { get; set; }
            public virtual A Next { get; set; }
        }
    }
}


hibernate.experiment.CircularDemo+A.hbm.xml file below:
Code:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" default-access="">
  <class name="hibernate.experiment.CircularDemo+A, hibernate.experiment, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" table="`A`" xmlns="urn:nhibernate-mapping-2.2">
    <id name="Id" type="Int32" column="Id">
      <generator class="identity" />
    </id>
    <many-to-one cascade="all" name="Next" column="Next_id" />
  </class>
</hibernate-mapping>



If someone could explain what I am doing wrong I would be grateful.


Top
 Profile  
 
 Post subject: Re: how to persist objects with circular references?
PostPosted: Wed Jul 22, 2009 2:49 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
I'm not absolutely sure, but probably your session doesn't get flushed automatically at the end of the using block. Try a s.Flush() after a1.Save() or wrap the whole operation in a transaction. Remember, just calling Save/Update/SaveOrUpdate doesn't persist to the database yet. That's not done until you flush the session or commit the transaction.

You're no gonna ask why one object is persisted to the database. There is one exception to what I said in the beginning. When you use database generated id's, hibernate will immediately insert the object when you call Save() to retrieve the id. But only for the object itself. The cascaded operatons won't be executet until you flush the session.

_________________
--Wolfgang


Top
 Profile  
 
 Post subject: Re: how to persist objects with circular references?
PostPosted: Wed Jul 22, 2009 3:12 am 
Newbie

Joined: Tue Jul 21, 2009 9:49 am
Posts: 3
wolli wrote:
I'm not absolutely sure, but probably your session doesn't get flushed automatically at the end of the using block. Try a s.Flush() after a1.Save() or wrap the whole operation in a transaction. Remember, just calling Save/Update/SaveOrUpdate doesn't persist to the database yet. That's not done until you flush the session or commit the transaction.

You're no gonna ask why one object is persisted to the database. There is one exception to what I said in the beginning. When you use database generated id's, hibernate will immediately insert the object when you call Save() to retrieve the id. But only for the object itself. The cascaded operatons won't be executet until you flush the session.


This is embarassing - that's exactly it. Thanks!


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