-->
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.  [ 7 posts ] 
Author Message
 Post subject: many-to-one lazy loading not working if property-ref is set
PostPosted: Mon Oct 20, 2008 9:50 am 
Code:

<class name="Ruolo" table="DBO_T_RUOLO">

<id name="id" column="id" type="integer">

<generator class="native"/>

</id>

<property name="codiceProdotto" column="CPRODOTTO" type="string"/>

<property name="codiceContratto" column="CCTR" type="string"/>

<property name="codiceCliente" column="CCLI" type="string"/>

<many-to-one name="tipoRuolo" column="CTIPORUOLO" class="TipoRuolo" property-ref="codiceTipoRuolo"/>

</class>




Code:

<class name="TipoRuolo" table="DBO_T_TIPORUOLO" proxy="TipoRuolo">

<id name="id" column="id" type="integer">

<generator class="native"/>

</id>

<property name="codiceTipoRuolo" column="CTIPORUOLO" type="string"/>

<property name="descrizioneTipoRuolo" column="DTIPORUOLO" type="string"/>

</class>




As you can see lazy loading should be enabled, having set the "proxy" attribute. However if I run the simple query:


Session session = HibernateUtil.currentSession();

Transaction tx= session.beginTransaction();

List ruoli = session.find("from Ruolo r where r.codiceCliente='325831'");

for (Iterator it = ruoli.iterator(); it.hasNext();) {

Ruolo r = (Ruolo) it.next();

out.println("\tcodice cliente: " + r.getCodiceCliente());

}

tx.commit();


the query does not reference the tipoRuolo property, nevertheless hibernates generates SQL queries also for TipoRuolo (non-lazy behaviour). This is the log file:


Hibernate: select ruolo0_.id as id, ruolo0_.CPRODOTTO as CPRODOTTO, ruolo0_.CCTR as CCTR, ruolo0_.CCLI as CCLI, ruolo0_.CTIPORUOLO as CTIPORUOLO from DBO_T_RUOLO ruolo0_ where (ruolo0_.CCLI='325831' )

Hibernate: select tiporuolo0_.id as id0_, tiporuolo0_.CTIPORUOLO as CTIPORUOLO0_, tiporuolo0_.DTIPORUOLO as DTIPORUOLO0_ from DBO_T_TIPORUOLO tiporuolo0_ where tiporuolo0_.CTIPORUOLO=?

Hibernate: select tiporuolo0_.id as id0_, tiporuolo0_.CTIPORUOLO as CTIPORUOLO0_, tiporuolo0_.DTIPORUOLO as DTIPORUOLO0_ from DBO_T_TIPORUOLO tiporuolo0_ where tiporuolo0_.CTIPORUOLO=?

Hibernate: select tiporuolo0_.id as id0_, tiporuolo0_.CTIPORUOLO as CTIPORUOLO0_, tiporuolo0_.DTIPORUOLO as DTIPORUOLO0_ from ........


I suppose that the non-lazy behaviour is somehow related to the "property-ref" attribute. Infact I modified the mapping file as follows:

Code:

<class name="Ruolo" table="DBO_T_RUOLO">

<id name="id" column="id" type="integer">

<generator class="native"/>

</id>

<property name="codiceProdotto" column="CPRODOTTO" type="string"/>

<property name="codiceContratto" column="CCTR" type="string"/>

<property name="codiceCliente" column="CCLI" type="string"/>

<many-to-one name="tipoRuolo" column="CTIPORUOLO" class="TipoRuolo"/>

</class>



Code:

<class name="TipoRuolo" table="DBO_T_TIPORUOLO" proxy="TipoRuolo">

<id name="codiceTipoRuolo" column="CTIPORUOLO" type="string">

<generator class="native"/>

</id>

<property name="descrizioneTipoRuolo" column="DTIPORUOLO" type="string"/>

</class>



hence I eliminated the property-ref attribute and set codiceTipoRuolo as primary key on the TipoRuolo class. Without changing anything in the java code and running the same query I got a lazy load of the Ruolo class (i.e. no SQL queries on the DBO_T_TIPORUOLO table).


So it seems to me that setting the "property-ref" attribute prevents from lazy loading of a class. How can I solve this problem? I need to map my entities using property-ref attribute.

Thanks.


Top
  
 
 Post subject:
PostPosted: Mon Oct 20, 2008 2:23 pm 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
This is expected behaviour. It happens because when you select data for the Ruolo class Hibernate doesn't know if there is an associated TipoRuolo or not or what the ID of that TipoRuolo is. Eg. Hibernate can't know if the 'tipoRuolo' property should be null or a proxy since there is no information about this in the 'DBO_T_RUOLO' table. To get this information Hibernate needs to query the DBO_T_TIPORUOLO table to find the ID of the TipoRuolo entity.

One possible workaround is to map the association with fetch="join": <many-to-one name="tipoRuolo" ... fetch="join" />. With this Hibernate should use only one query to get information from both tables. But I think you also have to modify all your queries to do a left fetch join. Eg:
from Ruolo r left fetch join r.tipoRuolo where r.codiceCliente='325831'

It may also work to enable lazy="no-proxy": <many-to-one name="tipoRuolo" ... lazy="no-proxy" /> but that requires byte-code manipulation as documented in: http://www.hibernate.org/hib_docs/v3/re ... properties

A third option may be to map the <many-to-one> as a <set>, but this may require to many changes in other places of your code to be really usable.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 21, 2008 5:55 am 
Hi nordborg,

Tks for your help, but I afraid it didn't work.
I tried all your tips.

I also changed the List to Set, but when I execute query its returns all same think.

[]s


Top
  
 
 Post subject:
PostPosted: Tue Oct 21, 2008 6:22 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Hmm... the first option should work. We have an identical case in our project which works just fine if we do LEFT JOIN FETCH in queries. If we leave it out we get the additional selects.

I have no experience with the byte-code manipulation needed for lazy property loading. It just seems like it should work from the documentation, but maybe it doesn't.

I never said that you should change a List to a Set. Since collections are always lazy it may work to replace the <many-to-one> (which isn't a list) with a <set>.

By the way: I can't find the session.find() method that you are using.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 21, 2008 6:50 am 
Hi,

I loading my entity using this:

Criteria select = sessao.createCriteria(Ruolo.class);
List objetos = select.list();

As you can see, I did not get what you said on <many-to-one> and Set.
Can you send me an example of your implementation or hbm files?

Tks


Top
  
 
 Post subject:
PostPosted: Tue Oct 21, 2008 7:10 am 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
This is not what you said in your first post. You said you were using
Code:
query: session.find("from Ruolo r where r.codiceCliente='325831'");


and I said that you should try changing it to:
Code:
from Ruolo r left join fetch r.tipoRuolo where r.codiceCliente='325831'


If you are using a Criteria you have to set the fetch mode: criteria.setFetchMode("tipoRuolo", FetchMode.JOIN).

We are not using Criteria queries in our project. The above is just from the docs.

As for the <set> option, it is nothing I would recommend since it may require lots of changes to code and queries. I have not used that option.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 21, 2008 8:28 am 
Sorry about the bad example.
I read this example in another post, and the problem was "almost" same.

But your last post cleared my mind. Now I undertood what you said.

Tks


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