-->
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.  [ 2 posts ] 
Author Message
 Post subject: get still does not hit the database after first time
PostPosted: Fri Sep 05, 2008 7:09 pm 
Beginner
Beginner

Joined: Thu Oct 25, 2007 1:21 pm
Posts: 29
Hi,

I have heard that session.get always hits the database. But what i have noticed was that get was not even hitting the database after first time.

Any ideas why this is happening? Then what is the difference between get and load?


thanks


Top
 Profile  
 
 Post subject:
PostPosted: Tue Sep 09, 2008 7:50 pm 
Expert
Expert

Joined: Tue May 13, 2008 3:42 pm
Posts: 919
Location: Toronto & Ajax Ontario www.hibernatemadeeasy.com
This little tutorial on the difference between load and get, and how the two work, might be helpful:

Quote:
Well, if you were to compare the load and get methods of the Hibernate Session, you'd think that they looked pretty darned similar; and you'd be correct, but there are subtle and very important differences.

First of all, the get method hits the database as soon as it is called. So, using the Hibernate Session's get method will always trigger a database hit. On the other hand, the load method only hits the database when a particular field of the entity is accessed. So, if we use the load method to retrieve an entity, but we never actually access any of the fields of that entity, we never actually hit the database. Pretty kewl, eh?

Well, actually, as kewl as the load method might sound, it actually triggers more problems than it solves, and here's why. If you initialize a JavaBean instance with a load method call, you can only access the properties of that JavaBean, for the first time, within the transactional context in which it was initialized. If you try to access the various properties of the JavaBean after the transaction that loaded it has been committed, you'll get an exception, a LazyInitializationException, as Hibernate no longer has a valid transactional context to use to hit the database.

So, while this code will work just fine?..

session.beginTransaction();
User user=(User)session.load(User.class, new Long(1));
System.out.println(user.getPassword());
session.getTransaction().commit();

.. this code will fail ?..

session.beginTransaction();
User user=(User)session.load(User.class, new Long(1));
session.getTransaction().commit();
System.out.println(user.getPassword());

.. and generate the following error, telling you that since the transaction was committed, there was no valid Session in which a read transaction against the database could be issued:

org.hibernate.LazyInitializationException:
could not initialize proxy - no Session

So, the big thing to take away from this is that with the load method, you can't really use your loaded JavaBeans after the transaction has been committed, whereas, with the get method you can, because all of the various properties of a JavaBean retrieved through the get method are initialized right away.
Loading Non-Existent Records

An important scenario under which you need to contrast the load and get methods of the Hibernate Session has to do with what happens when you provide a primary key that doesn't actually exist in the database. Well, with the get method, you are simply returned a null object, which is no big deal.

With the load method, there's also no initial problem when you provide an invalid primary key to the method. From what you can tell, Hibernate appears to hand you back a valid, non-null instance of the class in which you are interested. However, the problems start when you actually try to access a property of that instance - that's where you run into trouble.

Remember how I said the load method doesn't hit the database until a property of the bean is requested? Well, if you've provided a primary key that doesn't exist in your database to the load method, when it does go to the database for the first time, it won't be able to find the non-existent, associated record, and your code will cough up big time. In fact, looking up a field based upon a non-existent primary key with the Hibernate Session's load method triggers the following error:

org.hibernate.ObjectNotFoundException:
No row with the given identifier exists: [User#123]

public Object get (Class clazz, Serializable id) throws HibernateException
--Return the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance. (If the instance is already associated with the session, return that instance or proxy.)

public Object load (Class theClass,Serializable id) throws HibernateException
--Return the persistent instance of the given entity class with the given identifier, assuming that the instance exists. You should not use this method to determine if an instance exists (use get() instead). Use this only to retrieve an instance that you assume exists, where non-existence would be an actual error.

-Regurgitated Hibernate API JavaDoc

package com.examscam;
import org.hibernate.*; import com.examscam.model.User;
import org.hibernate.cfg.AnnotationConfiguration;
public class LoadRunner {

public static void main(String[] args) {
LoadRunner.callLoad(); LoadRunner.callGet();
}
public static void callLoad(){
AnnotationConfiguration config =
new AnnotationConfiguration();
config.addAnnotatedClass(User.class);
SessionFactory factory=
config.configure().buildSessionFactory();
Session session = factory.getCurrentSession();
session.beginTransaction();
try {
User user=
(User)session.load(User.class,new Long(1));
System.out.println(user.getPassword ());
} catch (ObjectNotFoundException e) {
e.printStackTrace();
}
session.getTransaction().commit();

/* System.out.println(user.getPassword());
This would fail!!! */

}
public static void callGet() {
AnnotationConfiguration config =
new AnnotationConfiguration();
config.addAnnotatedClass(User.class);
SessionFactory factory=
config.configure().buildSessionFactory();
Session session = factory.getCurrentSession();
session.beginTransaction();
User user=
(User)session.get(User.class,new Long(1));
System.out.println(user.getPassword());
session.getTransaction().commit();
/* no problem!!!*/
System.out.println(user.getPassword ());
}
}

When to use get? When to use load?

So, after comparing and contrasting the load and get methods, the natural question that arises is "when do I use the get, and when do I use load?" It's a good question.

For the most part, you'll probably use the get method most often in your code. If you ever want to use the JavaBean that you are retrieving from the database after the database transaction has been committed, you'll want to use the get method, and quite frankly, that tends to be most of the time. For example, if you load a User instance in a Servlet, and you want to pass that instance to a Java Server Page for display purposes, you'd need to use the get method, otherwise, you'd have a LazyInitializationException in your JSP.

On the other hand, if your goal is largely transactional, and you are only going to be accessing the JavaBean of interest within a single unit of work that will pretty much end once the transaction is committed, you'll want to use the load method. For that matter, if you want to ensure that the JavaBean of interest is completely in sync with the database when it is used, you'll want to be using the load method as well, as this will ensure the fields of the JavaBean are being loaded in from the database, and are not just being loaded from the memory of the Java Virtual Machine on which you are running.

Furthermore, the load method may be the method of choice if you know, and are absolutely sure, that the entity you are searching for exists in the database with the primary key you are providing. If you don't know for sure that an entity bearing your primary key exists in the database, you can use the get method, and check to see if the instance that gets returned from the method call returns null.

Hibernate's get and load methods tend to cause plenty of problems for new Hibernate developers. But with a good understanding of the differences between the two, you shouldn't have any problem avoiding LazyInitialization and ObjectNotFound Exceptions.


Tutorial on the difference between load and get

_________________
Cameron McKenzie - Author of "Hibernate Made Easy" and "What is WebSphere?"
http://www.TheBookOnHibernate.com Check out my 'easy to follow' Hibernate & JPA Tutorials


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