views:

84

answers:

2

I've run into a situation where the Hibernate object passed back from the query is unreliable.

Consider the following code:

MyClass myClass = myDAO.get(id);

myClass.getId(); //This works
myClass.getName(); //This returns null sometimes, and works sometimes

Here's my get Method:

@SuppressWarnings("unchecked")
public T get(ID id) 
{
    Session s = getSession();
    T entity = (T) s.load(getPersistentClass(), id);
    s.disconnect();
    return entity;
}

Now, I understand that this object is a proxy, and will be lazy loaded, but I would expect it to either always work, or never work. Am I doing something wrong here?

+3  A: 

This may or may not be the cause, but you probably shouldn't be using Session.load(), you should be using Session.get().

load() returns the persistent instance as currently loaded by hibernate, and it's possible this is partially populated depending on what happened before.

get() is more robust. Try that.

skaffman
load() is used for performance reasons (as per the Hibernate Team's recommendation). I'll give get() a shot, but I would still expect hibernate to fetch the member when asked for it...
Jesse
I had similar if not same problem using load, I changed to get() and all is good again()
jottos
I'm marking this as answered. I changed from load() to get() a little while ago, and haven't had an issue since.
Jesse
+1  A: 

Problem is "load" will load a proxy of the object and not actually hit the database. However, if the object has already been loaded (and populated) i.e. in the level 1 cache, it will provision that instance.

When you use load, it will only actually hit the database when absolutely necessary, i.e. when you ask for one of the fields of the object.

Get on the other hand will actually hit the database.

For your purposes I would recommend that whether you use load or get you make sure the object is populated before passing it back. Before you pass it back, call one of the getters on it. Then you can guarantee that it is populated.

A useful exercise would be to enable sql logging (org.hibernate.SQL=DEBUG), debug through it and have a look at what sql instructions are being executed.

You could also consider configuring the persistent object you're loading to be non lazy. That way, whether you use load or get, you're going to get a fully populated object every time.

Michael Wiles
I would avoid turning on eager fetching in the hibernate mapping as you suggested. Eager loading by default can result in major performance hits when loading collections of the mapped class or querying for views that do not need to display all the fields of the mapped class. This is why lazy loading is the default in Hibernate 3.x
Paul Morie