-->
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: not-null references on closed loop table configuration...
PostPosted: Wed Feb 01, 2006 9:01 am 
Beginner
Beginner

Joined: Thu Dec 08, 2005 6:49 pm
Posts: 49
I have just added not-null="true" to all of my many-to-one relations.
My schema contains two closed loops.
I now get a PropertyValueException stating that "not-null property references a null or transient value".

You'll have to excuse my lack of creativity here, but the following minimal example should replicate the problem.

Two and Three both reference One. Four references Two and Three.


Code:
using System;
using Iesi.Collections;

class One {
    private Guid _ID;
    private ISet _Twos;
    private ISet _Threes;

    public Guid ID {
        get { return _ID; }
        set { _ID = value; }
    }

    public One() {
        _Twos = new HashedSet();
        _Threes = new HashedSet();
    }

    public ISet Twos {
        get { return _Twos; }
        set { _Twos = value; }
    }

    public ISet Threes {
        get { return _Threes; }
        set { _Threes = value; }
    }
}

class Two {
    private Guid _ID;
    private One _One;
    private ISet _Fours;

    public Guid ID {
        get { return _ID; }
        set { _ID = value; }
    }

    public Two() {
        _Fours = new HashedSet();
    }

    public One One {
        get { return _One; }
        set { _One = value; }
    }

    public ISet Fours {
        get { return _Fours; }
        set { _Fours = value; }
    }
}

class Three {
    private Guid _ID;
    private One _One;
    private ISet _Fours;

    public Guid ID {
        get { return _ID; }
        set { _ID = value; }
    }

    public Three() {
        _Fours = new HashedSet();
    }

    public One One {
        get { return _One; }
        set { _One = value; }
    }

    public ISet Fours {
        get { return _Fours; }
        set { _Fours = value; }
    }
}

class Four {
    private Guid _ID;
    private Two _Two;
    private Three _Three;

    public Guid ID {
        get { return _ID; }
        set { _ID = value; }
    }

    public Two Two {
        get { return _Two; }
        set { _Two = value; }
    }

    public Three Three {
        get { return _Three; }
        set { _Three = value; }
    }
}


Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping
   xmlns="urn:nhibernate-mapping-2.0"
   assembly="Test"
>
  <class
    name="One"
    dynamic-update="true"
  >
    <id name="ID">
      <generator class="NHibernate.Id.GuidCombGenerator, NHibernate" />
    </id>
    <set name="Twos" inverse="true" cascade="all" lazy="true" >
      <key column="OneID" />
      <one-to-many class="Two" />
    </set>
    <set name="Threes" inverse="true" cascade="all" lazy="true" >
      <key column="OneID" />
      <one-to-many class="Three" />
    </set>
  </class>

  <class
    name="Two"
    dynamic-update="true"
  >
    <id name="ID">
      <generator class="NHibernate.Id.GuidCombGenerator, NHibernate" />
    </id>
    <many-to-one name="One" column="OneID" not-null="true" />
    <set name="Fours" inverse="true" cascade="all" lazy="true" >
      <key column="TwoID" />
      <one-to-many class="Four" />
    </set>
  </class>

  <class
    name="Three"
    dynamic-update="true"
  >
    <id name="ID">
      <generator class="NHibernate.Id.GuidCombGenerator, NHibernate" />
    </id>
    <many-to-one name="One" column="OneID" not-null="true" />
    <set name="Fours" inverse="true" cascade="all" lazy="true" >
      <key column="ThreeID" />
      <one-to-many class="Four" />
    </set>
  </class>

  <class
    name="Four"
    dynamic-update="true"
  >
    <id name="ID">
      <generator class="NHibernate.Id.GuidCombGenerator, NHibernate" />
    </id>
    <many-to-one name="Two" column="TwoID" not-null="true" />
    <many-to-one name="Three" column="ThreeID" not-null="true" />
  </class>
</hibernate-mapping>


Code:
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;

static class Program {
    static void Main() {
        Configuration config = new Configuration();
        config.Properties.Add("hibernate.connection.provider", "NHibernate.Connection.DriverConnectionProvider");
        config.Properties.Add("hibernate.dialect", "NHibernate.Dialect.MsSql2000Dialect");
        config.Properties.Add("hibernate.connection.driver_class", "NHibernate.Driver.SqlClientDriver");
        config.Properties.Add("hibernate.connection.connection_string",
                              "Data Source=(local);Integrated Security=SSPI;Initial Catalog=test2");

        config.AddAssembly("Test");
        new SchemaExport(config).Create(true, true);

        using (ISession session = config.BuildSessionFactory().OpenSession())
        using (ITransaction transaction = session.BeginTransaction()) {
            for (int i = 0; i < 3; i++) {
                One o = new One();

                for (int j = 0; j < 3; j++) {
                    Two tw = new Two();
                    Three th = new Three();

                    for (int k = 0; k < 3; k++) {
                        Four f = new Four();
                        tw.Fours.Add(f);
                        th.Fours.Add(f);
                        f.Two = tw;
                        f.Three = th;
                    }

                    o.Twos.Add(tw);
                    o.Threes.Add(th);
                    tw.One = o;
                    th.One = o;
                }
               
                session.Save(o);
            }

            transaction.Commit();
        }
    }
}



Any advice would be great.

Nathan


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 01, 2006 9:36 am 
Contributor
Contributor

Joined: Wed May 11, 2005 4:59 pm
Posts: 1766
Location: Prague, Czech Republic
Without looking closer at the object relationships, you can usually work around such problems by saving objects manually without relying on cascades. You should call Save on the objects in the order you would like them to be INSERTed.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 02, 2006 7:43 am 
Beginner
Beginner

Joined: Thu Dec 08, 2005 6:49 pm
Posts: 49
Sounds less than ideal. Is this not considered a bug? I would imagine this configuration is not all that uncommon.

Just to clarify, the relationship is as follows:

Image

The objects must be commited in the order One-Two-Three-Four or One-Three-Two-Four to ensure integrity.

Just to clarify, are you suggesting that I need to modify the inverse="true" or the cascade="all"? I'm still kinda new at this...


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.