Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 11 posts ] 
Author Message
 Post subject: Advantage of load() vs get()
PostPosted: Sun Feb 27, 2005 1:38 pm 
Newbie

Joined: Mon Feb 21, 2005 2:15 pm
Posts: 9
Hi
Can anyone tell me whats the Advantage of load() vs get() ?

Thanks,
Gayatri


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 27, 2005 7:40 pm 
Expert
Expert

Joined: Tue Nov 23, 2004 7:00 pm
Posts: 570
Location: mostly Frankfurt Germany
This is explained in the hibernate reference. One difference was performance if I remember properly and the other one is that load throws an unrecoverable Exception when no Object is found for the ID.

Regards Sebastian

_________________
Best Regards
Sebastian
---
Training for Hibernate and Java Persistence
Tutorials for Hibernate, Spring, EJB, JSF...
eBook: Hibernate 3 - DeveloperGuide
Paper book: Hibernate 3 - Das Praxisbuch
http://www.laliluna.de


Top
 Profile  
 
 Post subject: Re: Advantage of load() vs get()
PostPosted: Sun Feb 27, 2005 11:53 pm 
Beginner
Beginner

Joined: Mon Nov 29, 2004 5:34 pm
Posts: 35
Gayatri wrote:
Hi
Can anyone tell me whats the Advantage of load() vs get() ?

Thanks,
Gayatri


This from the book Hiberante in Action. Good one read this..

**************************************
Retrieving objects by identifier
The following Hibernate code snippet retrieves a User object from the database:
User user = (User) session.get(User.class, userID);
The get() method is special because the identifier uniquely identifies a single
instance of a class. Hence it’s common for applications to use the identifier as a
convenient handle to a persistent object. Retrieval by identifier can use the cache
when retrieving an object, avoiding a database hit if the object is already cached.
Hibernate also provides a load() method:
User user = (User) session.load(User.class, userID);


The load() method is older; get() was added to Hibernate’s API due to user
request. The difference is trivial:


If load() can’t find the object in the cache or database, an exception is
thrown. The load() method never returns null. The get() method returns
null if the object can’t be found.

The load() method may return a proxy instead of a real persistent instance.
A proxy is a placeholder that triggers the loading of the real object when it’s
accessed for the first time; we discuss proxies later in this section. On the
other hand, get() never returns a proxy.
Choosing between get() and load() is easy: If you’re certain the persistent
object exists, and nonexistence would be considered exceptional, load() is a
good option. If you aren’t certain there is a persistent instance with the given
identifier, use get() and test the return value to see if it’s null. Using load() has
a further implication: The application may retrieve a valid reference (a proxy) to a
persistent instance without hitting the database to retrieve its persistent state. So
load() might not throw an exception when it doesn’t find the persistent object
in the cache or database; the exception would be thrown later, when the proxy
is accessed.
Of course, retrieving an object by identifier isn’t as flexible as using arbitrary
queries.


**************************************
srigold


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 29, 2008 4:06 pm 
Newbie

Joined: Thu Mar 27, 2008 1:30 pm
Posts: 6
Sorry for reviving this thread, but that is not the only difference according to my research.

The get() method will return a FULL initialized object if nothing is on the session cache, that means several DB hits depending on your mappings.

While the load() method will return a proxy (or the instance if already initialized), allowing lazy initialization and thus better performance (which LaLiLuna already said)


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jun 08, 2008 3:39 pm 
Expert
Expert

Joined: Tue May 13, 2008 3:42 pm
Posts: 919
Location: Toronto & Ajax Ontario www.hibernatemadeeasy.com
Here's a little snippet from my website that you might find interesting.

http://jpa.ezhibernate.com/Javacode/learn.jsp?tutorial=27hibernateloadvshibernateget


The difference between a Hibernate load and a Hibernate get is a very common question, but the differences are important, although, at times, the difference between Hibernate load vs. get can be subtle.

Loading Entities with Hibernate

In an earlier tutorial, we looked at the hypothetical example where you had the primary key of an entity, and wanted to query the database and have Hibernate return the unique User instance associated with that primary key. The Haitian Voodoo required to perform that retrieval task looked something like this:

Code:
public static User retrieveFromId(int idValue) {
  AnnotationConfiguration config = 
                       new   AnnotationConfiguration();
  config.addAnnotatedClass(User.class);
  SessionFactory factory;
  factory = config.configure().buildSessionFactory();
  Session session = factory.getCurrentSession();
  session.beginTransaction();
  String queryString = "from User where id = :id";
  Query query = session.createQuery(queryString);
  query.setInteger("id", idValue);
  Object queryResult = query.uniqueResult();
  User user = (User)queryResult;
  session.getTransaction().commit();
  System.out.print(user.getPassword());
  return user;
}


Taking a primary key, and using it to demonstrate variable injection and the retrieval of a unique entity was very androgologically sound, but the fact of the matter is, if you actually have the primary key of an entity, there is a much easier, or should I say "a couple of much easier ways" to retrieve the corresponding entity from the database. We'll demonstrate those ways by coding a few methods into a new class called the LoadRunner.

The LoadRunner Class

The LoadRunner class is going to have a runnable main method, and two static methods, named callGet and callLoad, which will be used to demonstrate the two different ways you can get at an entity given its associated primary key. For now, I've coded in all the redundant code we need to have each method connect to the database, create a session, and start a transaction. I know that all of this Hibernate plumbing code is getting repetitive; we'll factor it out into a HibernateUtil class soon enough.

Code:
package com.examscam;
import org.hibernate.*;

import com.examscam.model.User;
import org.hibernate.cfg.AnnotationConfiguration;
public class LoadRunner {
  public static void callLoad(){
   AnnotationConfiguration config
                    = new AnnotationConfiguration();
   config.addAnnotatedClass(User.class);
   SessionFactory factory=
             config.configure().buildSessionFactory();
   Session session = factory.getCurrentSession();
   session.beginTransaction();
/***** load code will go here *****/
   session.getTransaction().commit();
  }
  public static void callGet() {
   AnnotationConfiguration config
                    = new AnnotationConfiguration();
   config.addAnnotatedClass(User.class);
   SessionFactory factory=
             config.configure().buildSessionFactory();
   Session session = factory.getCurrentSession();
   session.beginTransaction();
/***** get code will go here *****/
   session.getTransaction().commit();
  }
  public static void main(String[] args) {
    LoadRunner.callLoad();
    LoadRunner.callGet();
  }
}


The callGet Method

Within the session.beginTransaction() and the session.getTransaction().commit methods, we want to use the Hibernate Session to take a given primary key, and provide our program with the entity associated with that primary key in the database. It's all a pretty simple process. To get an entity from the underlying persistence store, all you have to do is call the Hibernate Session's get method, and provide two arguments: the Java class associated with the entity that your are retrieving, which in this case would be the User.class, and the actual primary key associated with the record. I know that I have a user in the database with a primary key of 1, so the number one will be used to test my methods.

Here's all the code you need to resurrect a User instance from the database using the Hibernate Session's load method:

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


And that's about it! You simply call the load method of the Hibernate Session, provide the class type and the primary key as parameters, and then cast the object that is returned from Hibernate back into the appropriate Java type. From there, you can do just about anything with your JavaBean that you want. In this case, I simply print out the password of the User instance. It's all just so easy.

Now, as I mentioned, there are two ways to pull an entity from the database, one of which is to use the get method of the Hibernate Session, and the other way is to use the load method. Compare and contrast the following code snippet that invokes the Session's load method to the code snippet that invoked the Session's get method. The difference is subtle, to say the least.
Code:
session.beginTransaction();
User user = (User)session.load(User.class, new Long(1));
System.out.println(user.getPassword());
session.getTransaction().commit();


Hibernate load vs. Hibernate get Methods

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?..

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


.. this code will fail ?..


Code:
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]

Quote:
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.)


Quote:
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

Code:
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.

http://jpa.ezhibernate.com/Javacode/learn.jsp?tutorial=27hibernateloadvshibernateget

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


Last edited by Cameron McKenzie on Mon Jun 09, 2008 9:17 am, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Mon Jun 09, 2008 7:54 am 
Newbie

Joined: Thu Mar 27, 2008 1:30 pm
Posts: 6
Thank you for the explanation Cameron, and it was a very good one!


Top
 Profile  
 
 Post subject: Thanks
PostPosted: Thu Aug 21, 2008 6:12 am 
Newbie

Joined: Sat Sep 01, 2007 1:32 am
Posts: 5
Thank you everyone specially Cameron McKenzie for such a extensive explanation. It helped to understand the difference very well.


Top
 Profile  
 
 Post subject: load not returning ObjectNotFoundException but an empty prox
PostPosted: Tue Feb 10, 2009 3:57 am 
Regular
Regular

Joined: Fri Nov 07, 2003 6:31 am
Posts: 104
Location: Beijing, China
sorry to reopen an old thread but it seems better than to create a new one.

According to the doc I understand that calling load() on a non existing object should throw a ObjectNotFoundException.
It actually does not and return a proxy. Only when trying to access a field will you get the expected ObjectNotFoundException.

Why is that so?

I'm actually using this with JPA.
getReference() calls Hibernate load() and should return EntityNotFoundException but returns a proxy
find() calls Hibernate get(), throw translated EntityNotFoundException in case of non existence, and finally return null.

It's a bit confusing to get the EntityNotFoundException when calling JPA find() /Hibernate get() where you expect only null and not get EntityNotFoundException when you expect it!

_________________
/nodje


Top
 Profile  
 
 Post subject: Re: Advantage of load() vs get()
PostPosted: Tue May 18, 2010 9:45 am 
Newbie

Joined: Sun Aug 06, 2006 8:54 am
Posts: 15
Hi all,

I'm happy to have found this thread because this has been puzzling me all day. I need a method that returns true if an entity exists in the database and false if it doesn't. Instead of using EntityManager.find(), I've used getReference to be more efficient. This is what I have written :

Code:
public boolean alreadyExists(Long id) {
    try {
        em.getReference(Book.class, id);
        return true;
    } catch (EntityNotFoundException e) {
        return false;
    }
}


It works well with EclipseLink... but not with Hibernate. The getReference doesn't throw the EntityNotFoundException when the entity is not found. It returns a proxy (something like Book_$$_javassist_0 instead of the Book entity). When I debug the AbstractEntityManagerImpl.getReference() method, I can see a weird message "Method threw 'javax.persistence.EntityNotFoundException' exception. Cannot evaluate Book_$$_javassist_0.toString()".

So, if like me you expect to have a EntityNotFoundException, this is why is doesn't happen (abstract from the JPA 2.0 specification about the getReference() method) :

Quote:
Get an instance, whose state may be lazily fetched. If the requested instance does not exist in the database, the EntityNotFoundException is thrown when the instance state is first accessed. (The persistence provider runtime is permitted to throw the EntityNotFoundException when getReference is called).


If you read carefully you'll see EntityNotFoundException is thrown when the instance state is first accessed. That means you need to call a getter on the proxy to get the exception. What's really disappointing with the spec is The persistence provider runtime is permitted to throw the EntityNotFoundException when getReference is called, so EclipseLink throws the exception as soon as the getReference method is invoked, but Hibernate throws the exception when the get method is called.

So, if you want your code to be portable across providers, call a getter on the entity.

Code:
public boolean alreadyExists(Long id) {
    try {
        Book b = em.getReference(Book.class, id);
        b.getId();
        return true;
    } catch (EntityNotFoundException e) {
        return false;
    }
}


A bit disapointing that the spec allows a "permitted to throw"

Antonio


Top
 Profile  
 
 Post subject: Re: Advantage of load() vs get()
PostPosted: Tue May 18, 2010 1:56 pm 
Expert
Expert

Joined: Wed Mar 03, 2004 6:35 am
Posts: 1240
Location: Lund, Sweden
Just a note/question. Usually, calling getId() on a Hibernate proxy doesn't cause it to be initialized. This may behave differently though when using an EntityManager. I have no idea since I have only used plain old Session objects and then it is "safe" to call getId() on a proxy without causing it to be initialized. It would be interesting to know if this is the same or different when using an EntityManager?


Top
 Profile  
 
 Post subject: Re: Advantage of load() vs get()
PostPosted: Tue May 18, 2010 5:47 pm 
Hibernate Team
Hibernate Team

Joined: Fri Oct 05, 2007 4:47 pm
Posts: 2296
Location: Third rock from the Sun
Quote:
If you read carefully you'll see EntityNotFoundException is thrown when the instance state is first accessed. That means you need to call a getter on the proxy to get the exception. What's really disappointing with the spec is The persistence provider runtime is permitted to throw the EntityNotFoundException when getReference is called, so EclipseLink throws the exception as soon as the getReference method is invoked, but Hibernate throws the exception when the get method is called.


hey there's a lot of noise here for a very simple concept: you should only use getReference() when you're sure it exists, use get() when you don't know and want the entitymanager to check for it.

So getReference() performs better as it doesn't perform a database query, as you're asking to skip this. As it doesn't perform a DB lookup, you can do getID() because it knows the id (you provided it yourself when calling getReference(id)), but as soon as you ask for another property he doesn't know the value and has to load it from database. It's like lazy loading the entity itself, as there are many usecases wherein you want a placeholder for the data but not likely using the attributes.

_________________
Sanne
http://in.relation.to/


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 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.