-->
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.  [ 4 posts ] 
Author Message
 Post subject: Integrating static lookup data with NHibernate sessions
PostPosted: Sat Oct 15, 2005 11:24 am 
Beginner
Beginner

Joined: Thu May 26, 2005 1:00 pm
Posts: 29
I am porting over an application to NHibernate, but I'm running into a snag. The app's object structure is categorized into regular CRUDable objects, and static, read-only objects (ie. "lookups"). The lookups are loaded from the database once into a set of hashtables when the application starts.

The CRUDable objects sometimes reference the lookup data in one-to-one, or one-to-many relationships. Problems arise when I try to update the CRUDable objects with the references from the lookups/hashtables. On save, I receive "NHibernate.PropertyValueException: not-null property references a null or transient value". I suspect this is because the static read-only lookup reference in the global hashtable is not in the CRUDable object's session. When I fetched the lookup via the session in a limited test case, everything seemed to go smoothly. Am I correct that this is the case?

For a more concrete, if contrived, example:
Code:
public class Supplier {
  int supplierId;
  Country country;
  //...getters/setters, etc.
}
//the following is a lookup
public class Country {
  int countryId;
  string name;
  //...getters/setters, etc.
}

The mapping files:
Code:
<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" schema="dbo" default-access="field">
   <class name="SpringAir.Objects.Supplier, SpringAir.Objects" table="Supplier">
      <id name="supplierId" column="SupplierId" access="field" unsaved-value="-1">
         <generator class="assigned" />
      </id>
      <many-to-one name="country" column="CountryId" not-null="true" cascade="none" />
   </class>

  <class name="SpringAir.Lookups.Country, SpringAir.Objects" table="Country" mutable="false">
    <id name="countryId" type="Int32" column="CountryId">
      <generator class="assigned" />
    </id>
  </class>
</hibernate-mapping>

A brief, contrived example of how it's used:
Code:
Supplier s = session.Load(typeof(Supplier), 1);
s.Country = countryTable[ this.lstCountries.SelectedItem.Value ]; //lookup the country based on a drop down selection
session.SaveOrUpdate(s);
session.Flush(); //<-- "NHibernate.PropertyValueException: not-null property references a null or transient value"

Unfortunately, I simply can't do away with the lookups at the moment, as it's deeply embedded in a great deal of code. If there's a way around this, I'd love to hear it!

If not, I've considered a few possible solutions, and I'd like some comments or pointers if it's not too much trouble:
  1. Upon opening a new session, iterate over all lookups and dump them into the session. This is infeasible because there are lookups with tens of thousands of records and sessions are created very frequently (ASP.NET).
  2. Adding some functionality so that NHibernate will query/reference the lookup tables instead of going to the database when loading these objects. Ways to do this:
    1. I'm not familiar with NHibernate internals, but I noticed the "class" has a "persister" attribute, which I believe references the NHibernate.Persister.IClassPersister interface. I'd investigate this avenue further, but it looks rather complicated, so I'd thought I'd solicit some opinions before investing the time.
    2. It just occured to me that the lookups can perhaps be viewed as a global cache of all of the lookup objects; might this avenue work? This cache must ONLY work for the lookup objects (ie. not the CRUDable objects). All lookups inherit from LookupBase which merely provides the scaffolding necessary to query the hastables based on given parameters.

Any thoughts and time-saving advice are much appreciated. :-)


Top
 Profile  
 
 Post subject:
PostPosted: Sun Oct 16, 2005 8:16 am 
Contributor
Contributor

Joined: Thu May 12, 2005 9:45 am
Posts: 593
Location: nhibernate.org
As countryId is assigned, make sure that its value is not 0 (else it will be considered as transient).

Your option 2.b. can also be enable (read NHibernate.Caches)

_________________
Pierre Henri Kuaté.
Get NHibernate in Action Now!


Top
 Profile  
 
 Post subject: Which countryId?
PostPosted: Sun Oct 16, 2005 8:54 am 
Beginner
Beginner

Joined: Thu May 26, 2005 1:00 pm
Posts: 29
As countryId is assigned, make sure that its value is not 0 (else it will be considered as transient).

Which countryId? If you mean the one in the Country object, then it should be fine. The lookup objects in the hashtables are all loaded via NHibernate, and as I mentioned, updating the Country via the session works, so the correct data should be there.

Is there some sort of "verbose logging" mode for NHibernate with which I can check the SQL generated or more trace NHibernate's decisions?


Top
 Profile  
 
 Post subject: Problem solved
PostPosted: Mon Oct 17, 2005 8:10 am 
Beginner
Beginner

Joined: Thu May 26, 2005 1:00 pm
Posts: 29
Naturally, this was a mistake on my part. When I didn't run into this same problem elsewhere, I investigated more thouroughly, and discovered that removing cascade="false" solved the problem.

Thanks for your help! :-)


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