-->
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.  [ 9 posts ] 
Author Message
 Post subject: Lazy initialization... everywhere?
PostPosted: Fri Jun 16, 2006 11:27 am 
Newbie

Joined: Fri Jun 16, 2006 11:20 am
Posts: 8
Hi, i'm implementing nHibernate in a medium-sized web project, basically based on web-services using the SOA architecture relying all the business logic behind web-services and using nHibernate for data access, the questions came when we've tried lazy initialization, it worked fine, but:

- Should we apply it to the entire project?
- Where should I pay attention where defining the lazy-loading behavior?

Thanx!
GermanK


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 16, 2006 11:50 am 
Expert
Expert

Joined: Fri May 13, 2005 5:56 pm
Posts: 308
Location: Santa Barbara, California, USA
Quote:
Should we apply it to the entire project?

in general, the Hibernate Team recommends using lazy loading for all associations.

Quote:
Where should I pay attention where defining the lazy-loading behavior?

in my opinion, i agree with the NH team, but certain instances seem to make more sense with lazy="false" in conjunction with <cache usage="read-only">. as an example, we have country objects each with a collection of states. in my mind, these are basically immutable and so here is the mapping:

Code:
<class
   name="Country"
   table="Country"
   lazy="true"
   mutable="false">
      
   <cache usage="read-only" />

   <id name="id" column="CountryID" type="Int32" unsaved-value="-1" access="field" >
      <generator class="identity" />
   </id>

   <property name="Name" column="`Name`" type="String" not-null="true" />
   <property name="SortOrder" column="SortOrder" type="Int32" not-null="true" />
      
   <bag name="States" table="State" cascade="delete-orphan" lazy="true" inverse="true" order-by="Name ASC" access="nosetter.camelcase">
      <cache usage="read-only" />
      <key column="CountryID" />
      <one-to-many class="State" />
   </bag>

</class>

<class
   name="State"
   table="State"
   mutable="false">
      
   <cache usage="read-only" />

   <id name="id" column="StateID" type="Int32" unsaved-value="-1" access="field" >
      <generator class="identity" />
   </id>

   <property name="Name" column="`Name`" type="String" not-null="true" />
   <property name="Abbreviation" column="Abbreviation" type="String" not-null="true" />
      
   <many-to-one name="Country" column="CountryID" class="Country" not-null="true" access="nosetter.camelcase" />
      
</class>


this basically caches all country and state objects and improves performance when using Country and State objects. we have another instance with Survey and Questions collection. the survey rarely changes but almost always is used with the Survey.Questions collection so lazy="false" and <cache usage="read-write" /> applies for us here.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 16, 2006 12:07 pm 
Newbie

Joined: Fri Jun 16, 2006 11:20 am
Posts: 8
Excelent Devon!
And thanks for the quick response ;)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 16, 2006 12:51 pm 
Senior
Senior

Joined: Sat Mar 25, 2006 9:16 am
Posts: 150
If you are serializing across web services, then how do you plan on lazy loading the objects on demand? When the objects are serailized to another application the connection is closed and you lost the ability to do any further lazy loading right?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 16, 2006 12:57 pm 
Newbie

Joined: Fri Jun 16, 2006 11:20 am
Posts: 8
grennis wrote:
If you are serializing across web services, then how do you plan on lazy loading the objects on demand? When the objects are serailized to another application the connection is closed and you lost the ability to do any further lazy loading right?


We're implementing an Entity Layer that translates the persistance objects (nhibernates) to propiertary Entities, and those are the serializable class...

The translation is made by using an internal reference of the NH entity and the properties of my propietary entity access the NH entity's properties to expose them in the serialization and access from the service layer.

(Please excuse my bad english)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 16, 2006 1:42 pm 
Senior
Senior

Joined: Sat Mar 25, 2006 9:16 am
Posts: 150
OK I understand. I have done something similiar and ended up with 4 classes for each object:

1 - NH mapped class
2 - Entity class service side
3 - Entity generated by web reference
4 - Entity class client side

To keep it under control we delete #3 and combine #2 and #4.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 16, 2006 1:47 pm 
Pro
Pro

Joined: Fri Nov 19, 2004 5:52 pm
Posts: 232
Location: Chicago, IL
One problem that you may run into is that if you try to serialize a class that has lazy="true" and it was lazily initialized, XML serialization will fail. This is because Castle.DynamicProxy doesn't generate a no arg constructor for the proxy class it generates. XmlSerializer which is what ASP.NET web services uses for serialization requires this and as a result the serialization will fail.

I asked the developer of DynamicProxy if he could add a no arg constructor. However, as far as I can tell, he really doesn't give a damn and doesn't take the time to even bother responding. His claim seems to be that an iterceptor needs to be passed to the object. However, in the case of web services, you really only need the class to act as a data structure and don't need the proxy behavior anyways because the object has already been lazy initialized when it was serialized.

It's probably not a good idea to try to return these objects from a web service method anyway, but, it would be nice to be able to do it for simple cases.

It sounds like you aren't returning NHibernate returned objects from your web service methods, so, maybe you won't run into that problem.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Jun 16, 2006 3:11 pm 
Newbie

Joined: Fri Jun 16, 2006 11:20 am
Posts: 8
jemiller wrote:
One problem that you may run into is that if you try to serialize a class that has lazy="true" and it was lazily initialized, XML serialization will fail. This is because Castle.DynamicProxy doesn't generate a no arg constructor for the proxy class it generates. XmlSerializer which is what ASP.NET web services uses for serialization requires this and as a result the serialization will fail.

I asked the developer of DynamicProxy if he could add a no arg constructor. However, as far as I can tell, he really doesn't give a damn and doesn't take the time to even bother responding. His claim seems to be that an iterceptor needs to be passed to the object. However, in the case of web services, you really only need the class to act as a data structure and don't need the proxy behavior anyways because the object has already been lazy initialized when it was serialized.

It's probably not a good idea to try to return these objects from a web service method anyway, but, it would be nice to be able to do it for simple cases.

It sounds like you aren't returning NHibernate returned objects from your web service methods, so, maybe you won't run into that problem.


That's not happening in my implementation, because from the beginning we did "wrap" the NH Entities into Domain Entities and mapped their properties to the NH Entities properties, so the serializations goes indirectly against the NH Entity, it serializes the Domain Entity.

Reduced sample:
Code:
public class NHEntity {

[...]

  private int _PersonID;
  private string _PersonName ;

[...]

  public int PersonName {
    get { return _PersonName }
    set { _PersonName = value; }
  }

[...]

}

[Serializable()]
public class DomainEntity: DomainEntityBase {

  private NHEntity _Internal;

  [...]

  public string PersonName {
    get { return _Internal.PersonName; }
    set { _Internal.PersonName = value; }
  }
 

}


That was the best approach we find to solve the Serialization problem, and also solved the IList serialization problem ;)


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jun 18, 2006 12:41 pm 
Newbie

Joined: Mon May 22, 2006 12:22 pm
Posts: 12
my two cents:

I didn't create different Entity Object Levels becuase I feel that they should be known throughout the Application Domain, = Domain Objects. The serialization issue is still an ongoing battle that I'm dealing with but I have one Entity Object project/namespace that's referenced from the DAO -> Business Rules -> Webservice -> Client (Dist. Winform App).

This makes the mapping for nHibernate completely relevant as the objects that are created are the domain objects. I was able to get around the Web Reference issue that MS creates by deleting the Domain objects that it creates and referencing my Domain Object namespace. All the "smarts" of the application truly lies in the Business Rules layer.


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