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.  [ 1 post ] 
Author Message
 Post subject: Interaction between many-to-one not-found and proxying
PostPosted: Sun Mar 02, 2008 11:30 am 
Newbie

Joined: Tue Oct 17, 2006 3:42 am
Posts: 2
I would like to understand the reason why the not-found attribute of a
many-to-one mapping influences the proxying behaviour of such associations.
If the not-found attribute is set to ignore the many-to-one is not loaded lazyly
and not proxy is used. If the not-found attribute is set to exception
the many to one uses lazy loading and a proxy is used.

Is this by design? And if so, what is the reason for it

Here is an example to reproduce the effect. (BTW: I am working with a legacy schema,
that is why I have assigned keys (not sure if they have any effect on the stuff described here)
and I use an IInterecptor to track the saved stated.)

I have the following mappings and classes:

Code:
using PlayGround.Classes;

namespace PlayGround.Play
{
   public class Dep:BaseEntity // BaseEntity just handles the IsSaved property as I have assigned keys
   {
      string _depName; int _depNo;

      virtual public int DepNo { get { return _depNo; } set { _depNo = value; } }

      virtual public string DepName { get { return _depName; } set { _depName = value; } }
   }
}

<hibernate-mapping default-cascade="all" xmlns="urn:nhibernate-mapping-2.2"
   default-access="field.camelcase-underscore" assembly="PlayGround" namespace="PlayGround.Play" >
   <class name="Dep" >
      <id name="DepNo" unsaved-value="0">
         <generator class="assigned" />
      </id>
      <property name="DepName" />
   </class>
</hibernate-mapping>

namespace PlayGround.Play
{
    public class Emp : BaseEntity
    {
        Dep _depNotFoundException; Dep _depNotFoundIgno; int _empId; string _lastName;

        public virtual Dep DepNotFoundException { get { return _depNotFoundException; } set { _depNotFoundException = value; } }

        public virtual Dep DepNotFoundIgno { get { return _depNotFoundIgno; } set { _depNotFoundIgno = value; } }

        public virtual int EmpId { get { return _empId; } set { _empId = value; } }

        public virtual string LastName { get { return _lastName; } set { _lastName = value; } }
    }
}


<hibernate-mapping default-cascade="all" xmlns="urn:nhibernate-mapping-2.2"
   default-access="field.camelcase-underscore" assembly="PlayGround" namespace="PlayGround.Play" >
   <class name="Emp" >
      <id name="EmpId" unsaved-value="0">
         <generator class="assigned" />
      </id>
      <property name="LastName" />
      <many-to-one name="DepNotFoundIgno" class="Dep" not-found="ignore"  />
      <many-to-one name="DepNotFoundException" class ="Dep" not-found="exception" />
   </class>
</hibernate-mapping>


The following Test creates the output further down:

Code:
[Test]
public void PlayWithEmpsAndDeps()
{
    SF.OpenNewLocalSession(); // recreates the schema
    Console.WriteLine(new string('\n', 2));
    SF.WithLocalDb(delegate(ISession s, ITransaction t)
                       {
                           Emp e = new Emp();
                           e.EmpId = 1;
                           Dep d = new Dep();
                           d.DepNo = 991;
                           Dep d2 = new Dep();
                           d2.DepNo = 888;
                           e.DepNotFoundException = d;
                           e.DepNotFoundIgno = d2;
                           s.Save(e);
                           t.Commit();
                       });

    Console.WriteLine(new string('\n', 2));
    SF.WithLocalDb(delegate(ISession s, ITransaction t)
                       {
                           Console.WriteLine("Test: Loading Emp");
                           Emp emp = s.Load<Emp>(1);
                           Console.WriteLine("Test: Type of returned object: " + emp.GetType().Name);
                           Console.WriteLine("Test: Accessing EmpId property");
                           Console.WriteLine("Test: " + emp.EmpId);
                           Console.WriteLine("Test: Accessing DepNotFoundIgno property");
                           Console.WriteLine("Test: " + emp.DepNotFoundIgno);
                           Console.WriteLine("Test: Type of prop DepNotFoundIgno: " + emp.DepNotFoundIgno.GetType());
                           Console.WriteLine("Test: Accessing DepNotFoundException property");
                           Console.WriteLine("Test: " + emp.DepNotFoundException);
                           Console.WriteLine("Test: Type of prop DepNotFoundException: " + emp.DepNotFoundException.GetType());
                       });
}



This is the output. I've added comments with //
Code:

// Schema creation output skipped
NHibernate: INSERT INTO Dep (DepName, DepNo) VALUES (@p0, @p1); @p0 = '', @p1 = '888'
NHibernate: INSERT INTO Dep (DepName, DepNo) VALUES (@p0, @p1); @p0 = '', @p1 = '991'
NHibernate: INSERT INTO Emp (LastName, DepNotFoundIgno, DepNotFoundException, EmpId) VALUES (@p0, @p1, @p2, @p3); @p0 = '', @p1 = '888', @p2 = '991', @p3 = '1'



Test: Loading Emp
//
// As Excpected: A proxy is created that just holds on to the id
Test: Type of returned object: CProxyTypePlayGround_PlayEmpPlay_NHibernate_ProxyINHibernateProxy1
//
// Funny, I thought accessing the Id property does not trigger a load.
// But as it turns out if you are not using the access strategy "property" this does not seem to work.
Test: Accessing EmpId property
NHibernate: SELECT emp0_.EmpId as EmpId127_0_, emp0_.LastName as LastName127_0_, emp0_.DepNotFoundIgno as DepNotFo3_127_0_, emp0_.DepNotFoundException as DepNotFo4_127_0_ FROM Emp emp0_ WHERE emp0_.EmpId=@p0; @p0 = '1'
//
// This is not as exspected.
// Quote from section 15.1.3:
//      "By default, NHibernate 1.2 generates proxies (at startup) for all persistent classes and uses them to enable
//       lazy fetching of many-to-one and one-to-one associations."
// But this is the many-to-one with the not-found="ignore" attribute. It behaves differently from the
// not-found="exception".
NHibernate: SELECT dep0_.DepNo as DepNo128_0_, dep0_.DepName as DepName128_0_ FROM Dep dep0_ WHERE dep0_.DepNo=@p0; @p0 = '888'
Test: 1
Test: Accessing DepNotFoundIgno property
Test: PlayGround.Play.Dep
Test: Type of prop DepNotFoundIgno: PlayGround.Play.Dep
Test: Accessing DepNotFoundException property
// This is the acccess to the property mapped with many-to-one not-found="exception". This one is really lazy loaded and uses a proxy.
NHibernate: SELECT dep0_.DepNo as DepNo128_0_, dep0_.DepName as DepName128_0_ FROM Dep dep0_ WHERE dep0_.DepNo=@p0; @p0 = '991'
Test: PlayGround.Play.Dep
Test: Type of prop DepNotFoundException: CProxyTypePlayGround_PlayDepPlay_NHibernate_ProxyINHibernateProxy1



Regards
Ralf


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

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.