-->
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.  [ 18 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: one-to-zero-or-one association and lazy fetching
PostPosted: Thu Jun 14, 2007 1:38 pm 
Beginner
Beginner

Joined: Wed Sep 06, 2006 12:08 pm
Posts: 48
Location: Warsaw - Poland - Europe - Milky Way
Hello Everybody

I bag you for help (it’s a third day of fight with this issue :(

The question is about one-to-zero-or-one association and lazy fetching (fetching on demand).

Let assume that we have 2 tables:

Code:
Person
======
person_id – primary key
name

Note
====
person_id – primary key for this table and foreign key to Person table
text


Additionally there is no strict 1 to 1 relation. Relation between Person and Note is: 1 to (0 or 1). So this is a reason why I cannot use ‘constrained’ HBM.XML mechanism.

I would like to have this:

Code:
class Person
{
   ...
   private Note note;


But when I have a ‘note’ member in Person class (mapped in different ways) Hibernate always generate complex SQL selects involving more than one table (Person table):
Code:
    select
      ...
    from
        Person
        left outer join Note   on ...
        left outer join Person on ...
    where
        personId=?

I would expect (and this is my question!) to get here only simple SQL query against Person table and have additional SELECT in case of some operations on note class member.

I know that documentation stands:
Note that if constrained="false", proxying is impossible and Hibernate will eager fetch the association!

But on Hibernate forum I found many posts with hints that instrumentation could helpful for me. But, unfortunately, I don’t know how to use instrumentation in this particular case.

And maybe there is other way to handle such cases.

Note plase, that I would like to have this one-to-one association because it would be useful to use it with conjunction with runtime fetch strategies where at runtime I can decide in my Criteria queries, what I would like to load via JOINs.

Help pliiiiis.

Kind regards,
Adam
Code:


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 14, 2007 3:16 pm 
Senior
Senior

Joined: Tue Jun 12, 2007 4:49 pm
Posts: 127
Location: India
In person class try many-to-one mapping with not-null="false".

Regards,
Jitendra


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 15, 2007 8:31 am 
Beginner
Beginner

Joined: Wed Sep 06, 2006 12:08 pm
Posts: 48
Location: Warsaw - Poland - Europe - Milky Way
Hello Jitendra

Unfortunately it doesn’t work either. Your suggestion works perfectly but for strict 1-1 relations only.

But I have a 1 to (0 or 1) relation. When there are corresponding records in Note table for ALL records from Person table everything works fine. But when I process a record from Person table with NO corresponding record in Note table, during accessing note’s property from Person object:

Code:
person.getNote().getSomething();


... I have ObjectNotFoundException exception.

I have tried all 4 combinations of “not-null” and “unique” HBM.XML settings (in many-to-one option) but every time I got a ObjectNotFoundException exceptions (for persons with no corresponding record in Note table).

Any other clues?

Regards,
Adam

PS.
Thank for your answer.


Top
 Profile  
 
 Post subject: Re:
PostPosted: Fri Jun 15, 2007 5:02 pm 
Senior
Senior

Joined: Tue Jun 12, 2007 4:49 pm
Posts: 127
Location: India
Here you go :-)

In many-to-one mapping you can put :

not-found="ignore"


This will not thru exception, but will return null.


Dun forget the credit :-)

Regards,
Jitendra


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 18, 2007 9:18 am 
Beginner
Beginner

Joined: Wed Sep 06, 2006 12:08 pm
Posts: 48
Location: Warsaw - Poland - Europe - Milky Way
Hello Jitendra

Unfortunately it is not exactly what I am looking for :(

Once again: I have a one to zero-or-one relation between Person and Note entities. Additionally I want:
* to load Person.note member on demand (i.e. lazily)


When I applied your tip (not-found="ignore") like this:
Code:
    <class name="model. Person">
      ...
      <many-to-one name="note"
      class="model.Note"
      column="personid"
      insert="false"
      update="false"
      cascade="all"
      not-null="false"
      not-found="ignore"
      />


... then when I try to load Person entity then Note entity is loaded eagerly. In other words with not-found="ignore" I have 2 SQL SELECTs (against Person and Note tables) or 1 complex joined SQL SELECT statement against those two tables (depending on fetch="join" or fetch="select" setting).

btw:
Thanks for your tips! Didn’t solve my problem but ... credited ;)

Kind regards,
Adam / Poland


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 18, 2007 3:09 pm 
Senior
Senior

Joined: Tue Jun 12, 2007 4:49 pm
Posts: 127
Location: India
Thanks for the credit. Though you did not say but i am assuming you are not getting exception so thats one part solved.

For making it fetch lazily, you need to explicitly set lazy="true" in many-to-one, as by default its set to lazy=false, hence eager fetching.

Hope it helps..

cheers!
Jitendra


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 19, 2007 5:13 am 
Beginner
Beginner

Joined: Wed Sep 06, 2006 12:08 pm
Posts: 48
Location: Warsaw - Poland - Europe - Milky Way
Hello Jitendra

No, no, no :)
This your tip with lazy="true" doesn’t work either :(

btw:
There is no lazy="true" option for many-to-one mappings. Valid settings are: lazy="proxy|no-proxy|false". But I assume you meant “proxy”. And default setting for many-to-one is lazy=”proxy”, not lazy=”false” ;)

As far as I see it is not possible in Hibernate to gain what I am trying to get (and what was described by me, here in this forum thread).

Once again: I would like to have a following behavior:

Code:
Person person = (Person) session.get(Person.class, id); // line 1 //


For “line 1” I want to have SQL SELECT against PERSON table only.



Code:
Note note = person.getNote(); // line 2 //


In “line 2” I would like to have a second SQL SELECT shot to load data related to Note entity. Because I have 1 to (0 or 1) relation between Person and Note entities, it is possible that such SELECT will return no row and then person.getNote() will return null.

And I don’t want to be slapped by ObjectNotFoundException too :)

As I said, as far as I see it is not possible in Hibernate.

Want a bet? :) Polish Zubrowka is already waiting for someone who can show how to obtain such behavior in Hibernate :) ( http://en.wikipedia.org/wiki/Zubrowka )

Kind regards,
Adam


Top
 Profile  
 
 Post subject: Re:
PostPosted: Tue Jun 19, 2007 8:03 am 
Senior
Senior

Joined: Tue Jun 12, 2007 4:49 pm
Posts: 127
Location: India
Which version of hibernate are you using. I am testing on hibernate 3.2.4.

I have the thing working.Will give you my test case later after verification :-) ..

Regards,
Jitendra


Last edited by jits_1998 on Tue Jun 19, 2007 8:34 am, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 19, 2007 8:14 am 
Beginner
Beginner

Joined: Wed Sep 06, 2006 12:08 pm
Posts: 48
Location: Warsaw - Poland - Europe - Milky Way
Hi Jitendra

All latest versions at my side: Hibernate 3.2.4.sp1.

btw:
You said that you have an appropriate piece of code which can handle my expectation. Could you copy+paste this code here? I would like to study your solution.

Kind regards,
Adam


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 19, 2007 8:36 am 
Senior
Senior

Joined: Tue Jun 12, 2007 4:49 pm
Posts: 127
Location: India
Yeah will do that. Its on my home pc. I am in office right now. will do it later today.

cheers!
Jitendra


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 19, 2007 3:20 pm 
Senior
Senior

Joined: Tue Jun 12, 2007 4:49 pm
Posts: 127
Location: India
Here you go :
Test java code:
Code:

      Session session = factory.openSession();
      ClassA a = new ClassA();
      
      ClassB b = new ClassB();
      
      b.setClassA(a);
      
      a.setNote("This is note");
      
      b.setName("This is first b");
      
      session.save(b);
      
      session.flush();
      
      session.close();
      
      session = factory.openSession();
      
      b = (ClassB)session.load(ClassB.class, b.getId());
      
      System.out.println(" classB fetched class=>"+ (b.getClassA().getClass().getName()));
      
      System.out.println("From a:"+a.getNote());
      
      System.out.println(" classB fetched class=>"+ (b.getClassA().getClass().getName()));
      
      session.close();
      
      session = factory.openSession();
      
      b = new ClassB();
      
      session.save(b);
      
      session.flush();
      
      session.close();
      
      session = factory.openSession();
      
      b = (ClassB)session.load(ClassB.class, b.getId());
      
      System.out.println("No exception thrown when there was no when A = " + (b.getClassA()) );
   


hbm.xml
Code:
<class name="ClassA" lazy="true" >

      <id name="id" type="long">
          <generator class="increment"/>
      </id>

      
      <property name="note"/>
      

   </class>

   <class name="ClassB" >
      <id name="id">
         <generator class="increment" />
      </id>
      
      <property name="name"/>
      
      <many-to-one name="classA" class="ClassA" column="a_id"
                unique="true"
                cascade="all" lazy="proxy"/>
      
   </class>


Class is rather simple to write.

You will see lazy fetching using cglib. This is closest you can get to not getting the complete class.

*Do rate if this helps*

Regards,
Jitendra


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jun 19, 2007 4:45 pm 
Senior
Senior

Joined: Tue Jun 12, 2007 4:49 pm
Posts: 127
Location: India
http://www.hibernate.org/162.html

Looks like a discussion just for you :-).

cheers!
Jitendra


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 20, 2007 7:11 am 
Beginner
Beginner

Joined: Wed Sep 06, 2006 12:08 pm
Posts: 48
Location: Warsaw - Poland - Europe - Milky Way
Hello Jitendra

Code presented by you works perfectly but ... you have changed database schema! :)

Schema presented by you is:
Code:
ClassB
======
id   – primary key
name
a_id – foreign key to ClassA

ClassA
======
id   - primary key
note


... but my schema is (like I have described in my initial post):

Code:
ClassB
======
id   – primary key
name

ClassA
======
id   - primary key of ClassA and foreign key to ClassB
note


I cannot change my database schema (it’s a legacy db).
Many thanks for your suggestion but it is not solving my problem :(

And, of course, I know this page http://www.hibernate.org/162.html :) (but thanks for this address anyway)
Unfortunately I haven’t found a solution on that page too :(

Kind regards,
Adam


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jun 20, 2007 12:41 pm 
Senior
Senior

Joined: Tue Jun 12, 2007 4:49 pm
Posts: 127
Location: India
ah oh .. How do you expect these two to link if there is no shared key in your db ?

Join table ?? i haven't used that . but are you allowed to add table in your schema else there is no solution possible.

Regards,
Jitendra


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jun 21, 2007 5:22 am 
Beginner
Beginner

Joined: Wed Sep 06, 2006 12:08 pm
Posts: 48
Location: Warsaw - Poland - Europe - Milky Way
Hi Jitendra

I don’t understand what do you mean.

I have a schema like this (Oracle database):

Code:
CREATE TABLE classB1
(
   ID   NUMBER       NOT NULL,
   NAME   VARCHAR2(1),

   CONSTRAINT PK_classB1 PRIMARY KEY (ID)
)

CREATE TABLE classA1
(
   ID   NUMBER       NOT NULL,
   NOTE VARCHAR2(1),
   CONSTRAINT PK_classA1 PRIMARY KEY (ID)
)


ALTER TABLE CLASSA1
ADD CONSTRAINT CLASSA1_CONSTRAINT
FOREIGN KEY (ID)
REFERENCES CLASSB1 (ID)


So I think that such situation can be described as “shared key”, am I right?

And such schema is easy to be mapped. You can find an example in official Hibernate Core documentation (have a look at http://www.hibernate.org/hib_docs/v3/reference/en/html_single/#assoc-unidirectional-121 ant a phrase “A unidirectional one-to-one association on a primary key”).
Solution described in the documentation obviously works but this solution is not lazy. And my original question in this forum thread was: “is it possible to gain a laziness for such two tables?”.

Kind regards,
Adam


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 18 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:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.