-->
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.  [ 19 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Fetch foreign key as a property
PostPosted: Wed Mar 12, 2008 8:20 am 
Beginner
Beginner

Joined: Wed Jan 16, 2008 4:00 am
Posts: 41
Hello everybody!

Is it possible to fetch a foreign key as a property?

it actually is if I map the foreignkeycolumn as a property. But when exporting the database schema I get a duplicate columnname exception.
I'm looking for a cleaner way to do so..

thx in advance & kind regards!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 12, 2008 8:23 am 
Regular
Regular

Joined: Wed Jan 25, 2006 1:11 am
Posts: 118
Location: Copenhagen, Denmark
Why would you do that?

If its for querying on this you can get the same result by accesing the identifier on the property.

If its because you need the identifier but don't want to lazy load the whole identity you have nothing to fear. Accessing the identifier on the proxy will not fetch the object from the database


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 12, 2008 10:03 am 
Beginner
Beginner

Joined: Wed Jan 16, 2008 4:00 am
Posts: 41
oh, didn't know that!
thx a lot


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 19, 2008 4:40 am 
Beginner
Beginner

Joined: Wed Jan 16, 2008 4:00 am
Posts: 41
jta wrote:
Why would you do that?

If its for querying on this you can get the same result by accesing the identifier on the property.

If its because you need the identifier but don't want to lazy load the whole identity you have nothing to fear. Accessing the identifier on the proxy will not fetch the object from the database


Actually the Identifier of the object is null!

I have a simple many-to-one:
<many-to-one name="parent" column="id" class="ParentClass"/>

child.parent.id returns null :-/

Is this the default behavior, or should the Identifier really be filled?!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 19, 2008 8:38 am 
Regular
Regular

Joined: Wed Jan 25, 2006 1:11 am
Posts: 118
Location: Copenhagen, Denmark
It should be filled the following testcase should work:

Code:
public void TestIdentifier()
{
    long childid = 0;
    long parentid = 0;

    using(ISession sess = OpenSession())
    {
        Parent parent1 = new Parent();
        Child child1 = new Child();
        parent1.AddChild(child1);
        sess.Save(parent1);
        sess.Save(child1);
        childid = child1.Id;
        parentid = parent1.Id;
    }

    using(ISession sess = OpenSession())
    {
        Child child1 =
            sess.CreateQuery("from Child c where c.id = ?").SetParameter(0, childid).UniqueResult<Child>();
        Assert.AreEqual(parentid, child1.Parent.Id);
        Assert.IsFalse(NHibernateUtil.IsInitialized(child1.Parent));
       
    }
}


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 19, 2008 9:29 am 
Beginner
Beginner

Joined: Wed Jan 16, 2008 4:00 am
Posts: 41
should this work too?

ICollection<Child> child1 =
sess.CreateQuery("select elements(p.Children) from Parent p where p.id = ?").SetParameter(0, parentId).List<Child>();
foreach(Child c in child1)
{
Assert.AreEqual(parentid, c.Parent.Id);
Assert.IsFalse(NHibernateUtil.IsInitialized(c.Parent));
}

thats the way I fetch my childelements? As they are composite elements, I cant fetch them with:
select c from Parent p join p.Children c where p.Id = ?

this results in an exception saying:"Could not find Id attribute of children" - b/c my children are actually composite elements.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 19, 2008 9:43 am 
Regular
Regular

Joined: Wed Jan 25, 2006 1:11 am
Posts: 118
Location: Copenhagen, Denmark
Hmmm, im not sure how this will work components. Perhaps someone else will now. It would be easier to help if you supplied the mapping file of the failing case. The most ideal would be to write a small sample to reproducere the error with Testcase mappingfiles and class declarations :-)


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 01, 2008 3:50 am 
Beginner
Beginner

Joined: Wed Jan 16, 2008 4:00 am
Posts: 41
Allright, I set up a sample application considering another problem, but I quickly wrote a testcase for this issue too, here are the files:

mapping file:

Child:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="DaoLayer.Entity.Child, DaoLayer" table="children">
    <id name="ID" column="childId" type="String">
      <generator class="uuid.hex" />
    </id>
    <property name="Name" column="name" type="string" />
    <many-to-one name="Parent" column="aId" class="DaoLayer.Entity.A, DaoLayer"/>
  </class>
</hibernate-mapping>


Parent:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class name="DaoLayer.Entity.A, DaoLayer" table="entities">
    <id name="ID" column="aId" type="String">
      <generator class="uuid.hex" />
    </id>
    <set name="Children" cascade="all-delete-orphan">
      <key column="aId" />
      <one-to-many class="DaoLayer.Entity.Child, DaoLayer" />
    </set>
  </class>
</hibernate-mapping>


Testcase:
Code:
[TestMethod()]
        public void ProxyFetchingIDAvailableTest()
        {
            IDaoObject daoobj = (IDaoObject) ContextRegistry.GetContext().GetObject("DaoObject");
            IObjectFactory objfac = (IObjectFactory)ContextRegistry.GetContext().GetObject("ObjectFactory");

            IA a = objfac.CreateA();

            for (int i = 0; i < 1; i++)
            {
                IChild child = objfac.CreateChild();
                child.Name = "test" + i.ToString();
                a.Children.Add(child);
            }

            IA a2 = (IA)daoobj.Save(a);

            // load a child and check if a2.id can be retrieved

            IChild persistedChild = objfac.CreateChild();
            foreach (IChild child in a2.Children)
            {
                daoobj.LoadObjectById(persistedChild, child.ID);
                Assert.IsNotNull(persistedChild.Parent.ID);
            }
           
           

        }


this testcase failes, b/c parent.Id is always null!

Its a very simple example it it doens't work. I'd really like to know if this is supposed to work with nhibernate!

I retrieve child with this class:
Code:
    public class DaoObject : HibernateDaoSupport, IDaoObject
    {
      public void LoadObjectById(object obj, string _id)
        {
            try
            {
                this.HibernateTemplate.Load(obj, _id);
            }
            catch (Exception)
            {
               
                throw;
            }
        }
    }




thx in advance n' regards!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 01, 2008 4:11 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
Two things:

- you should mark one end (usually the many) of the association as inverse
Code:
<set name="Children" cascade="all-delete-orphan" inverse="true">
      <key column="aId" />
      <one-to-many class="DaoLayer.Entity.Child, DaoLayer" />
    </set>

- you have to assign the parent to the child object manually, hibernate doesn't do that for you.

Then you're testcase should work.

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 01, 2008 4:30 am 
Beginner
Beginner

Joined: Wed Jan 16, 2008 4:00 am
Posts: 41
one thing:
If I add inverse="true", then of course I have to add the parent to the child object manually! But why I should I do that? Adding inverse="true" to one end of the relation is generally ok, but nevertheless it's a matter of requirements and having no inverse="true" is ok in this scenario.

Nevertheless I gave it a try. As expected, the testcase still doesn't work!

Code:
[TestMethod()]
        public void ProxyFetchingIDAvailableTest()
        {
            IDaoObject daoobj = (IDaoObject) ContextRegistry.GetContext().GetObject("DaoObject");
            IObjectFactory objfac = (IObjectFactory)ContextRegistry.GetContext().GetObject("ObjectFactory");

            IA a = objfac.CreateA();
            IA a2 = (IA)daoobj.Save(a);

            string childId = "";
            for (int i = 0; i < 1; i++)
            {
                IChild child = objfac.CreateChild();
                child.Name = "test" + i.ToString();
                child.Parent = a;
                childId = ((IChild)daoobj.Save(child)).ID;
            }

            // load a child and check if child.Parent.Id can be retrieved

            IChild persistedChild = objfac.CreateChild();
            daoobj.LoadObjectById(persistedChild, childId);
            Assert.IsNotNull(persistedChild.Parent.ID);
        }


Still the Id is null!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 01, 2008 5:00 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
What are you doing inside your Save() method ? Is a2 a new object or simply a reference to a ? If it's anew object, is it possible that the generated id is only assigned to a2 and not to a ?

Just to make sure, you have checked that the parent id is really inserted into the child record ?

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 01, 2008 5:18 am 
Beginner
Beginner

Joined: Wed Jan 16, 2008 4:00 am
Posts: 41
Code:
IA a2 = (IA)daoobj.Save(a);


this line can be subistuted with

Code:
IA a = (IA)daoobj.Save(a);


and would deliver the same result again.

I've double checked if children are persisted with the right foreign key - they are!

When loading the child via the childId, I retrieve the right child object with a name, but Parent is of type CProxyXXXXX and all attributes are null - even .ID

edit: still I don't see if inverse="true" should influence this proxyFetching behaviour?!


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 01, 2008 5:32 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
Inverse hasn't anything todo with the proxy fetching, just mentioned that because you had to entities which were both "owning" the association, which may result in problems as far as I can remember. And in your first test case, you didn't set the parent, I supposed the parent id wouldn't be written into the db:

Code:
            IA a = objfac.CreateA();

            for (int i = 0; i < 1; i++)
            {
                IChild child = objfac.CreateChild();
                child.Name = "test" + i.ToString();
                a.Children.Add(child);
            }

            IA a2 = (IA)daoobj.Save(a


So on the first look, it looked for me that the parent wasn't really written to the db (at least in the testcase), explaining your problem (using proxy or not).

Have you found anything suspicious in the log (with DEBUG logging and hibernate.show_sql="true") ? Can you see a select for the parent ?

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 01, 2008 5:35 am 
Expert
Expert

Joined: Thu Dec 14, 2006 5:57 am
Posts: 1185
Location: Zurich, Switzerland
Btw. when you set lazy to false, is it working then ?

_________________
--Wolfgang


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 01, 2008 5:35 am 
Beginner
Beginner

Joined: Wed Jan 16, 2008 4:00 am
Posts: 41
of course they are fetched if i set lazy="false"

The parent element is not fetched, but the id of the element is fetched... i can show you the output in a minute...

Code:
NHibernate: INSERT INTO entities (aId) VALUES (?); p0 = 'bdfa211a5846435cb1ba1326149ae39a'
2008/04/01 11:37:28:479 [DEBUG] Spring.Data.NHibernate.SessionFactoryUtils - Closing Hibernate Session
2008/04/01 11:37:28:482 [DEBUG] Spring.Data.NHibernate.SessionFactoryUtils - Opening Hibernate Session
2008/04/01 11:37:28:483 [DEBUG] Spring.Data.NHibernate.HibernateAccessor - Eagerly flushing Hibernate session
NHibernate: INSERT INTO children (name, aId, childId) VALUES (?, ?, ?); p0 = 'test0', p1 = 'bdfa211a5846435cb1ba1326149ae39a', p2 = '1eec71ec293d48ed93a1c8b90100c5c2'
2008/04/01 11:37:28:523 [DEBUG] Spring.Data.NHibernate.SessionFactoryUtils - Closing Hibernate Session
2008/04/01 11:37:28:524 [DEBUG] Spring.Data.NHibernate.SessionFactoryUtils - Opening Hibernate Session
NHibernate: SELECT child0_.childId as childId2_0_, child0_.name as name2_0_, child0_.aId as aId2_0_ FROM children child0_ WHERE child0_.childId=?; p0 = '1eec71ec293d48ed93a1c8b90100c5c2'
2008/04/01 11:37:28:667 [DEBUG] Spring.Data.NHibernate.HibernateAccessor - Eagerly flushing Hibernate session
2008/04/01 11:37:28:667 [DEBUG] Spring.Data.NHibernate.SessionFactoryUtils - Closing Hibernate Session


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

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:
cron
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.