views:

242

answers:

4

An application I'm working on does all its queries by identifier using session.load(). Given the chaos it causes when it can't find the identifier and throws an exception, I'm thinking of swapping it over to session.get(). But before I do that, it's such a fundamental part of the system that I want to make sure there's absolutely no other difference between the two methods. Is there any reason you can think of why the original developers would have chosen load() over get() aside from the handling of invalid IDs?

EDIT: As stated above, I'm fully aware that get returns false and load throws an exception. I'm asking if there's any OTHER way that they differ.

A: 

As usual, the best reference for this is the documentation:

Session.get():

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, or a proxy for the instance, is already associated with the session, return that instance or proxy.)

Session.load():

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.

So, the difference is the way that non-existing instances are treated.

matt b
Right, but I was asking if there was any *other* difference. I'm trying to read the minds of developers long since gone and to me it makes no sense that they would use load. So, I'm trying to think of any other reason they might have had.
abeger
+2  A: 

Isn't it so that Get never returns a proxy whereas Load does ?

http://ayende.com/Blog/archive/2009/04/30/nhibernate-ndash-the-difference-between-get-load-and-querying-by.aspx

I think that this is important:

Why is this useful? Well, if you know that the value exist in the database, and you don’t want to pay the extra select to have that, but you want to get that value so we can add that reference to an object, you can use Load to do so: The code above will not result in a select to the database, but when we commit the transaction, we will set the CustomerID column to 1. This is how NHibernate maintain the OO facade when giving you the same optimization benefits of working directly with the low level API.

From the NH 2.0 ref documentation:

Note that Load() will throw an unrecoverable exception if there is no matching database row. If the class is mapped with a proxy, Load() returns an object that is an uninitialized proxy and does not actually hit the database until you invoke a method of the object. This behaviour is very useful if you wish to create an association to an object without actually loading it from the database.

If you are not certain that a matching row exists, you should use the Get() method, which hits the database immediately and returns null if there is no matching row.

Frederik Gheysels
At least in Java Hibernate, .get() *can* return a proxy, if a proxy has already been created for that entity in the session. That way you don't end up with getting proxy-references through one route and non-proxy-references through another (breaking the 'you can use == to test for objects mapped to the same row' feature)
araqnid
A: 

Hi,

A good approach is shown as follows

If you need to call a getter method, then use get method. get method hits the database.

public class AccountServiceImpl implements AccountService {

    private SessionFactory sessionFactory;

    public BigDecimal getBalance(Integer acountId) {
        // You need to know your balance
        // So you need to use get method to access the database
        Account account = (Account) sessionFactory.getCurrentSession().get(Account.class, accountId);

        return account.getBalance();
    }

}

If you need to call both getter and setter method, use get method.

In response to ChssPly's comment:

JPA with Hibernate book says about load method

The load() method always tries to return a proxy, and only returns an initialized object instance if it’s already managed by the current persistence context.

And

It hits the database as soon as you try to access the returned placeholder and force its initialization

Thus, he is right when you set up a single property.

But There is the following scenario shown in JPA with Hibernate book

It’s common to obtain a persistent instance to assign it as a reference to another instance. For example, imagine that you need the item only for a single purpose: to set an association with a Comment: aComment.setForAuction(item).

If this is all you plan to do with the item, a proxy will do fine; there is no need to hit the database. In other words, when the Comment is saved, you need the foreign key value of an item inserted into the COMMENT table.

The proxy of an Item provides just that: an identifier value wrapped in a placeholder that looks like the real thing.

regards,

Arthur Ronald F D Garcia
Your first example does not illustrate a good use of `load()`. Your `User` instance will be physically loaded the very moment you invoke `setPassword()` method. A more appropriate scenario would involve loading / setting another entity on a @ManyToOne relationship.
ChssPly76
Thank you, I have seen what you said and you right. But i do not understanding why Hibernate needs to select when you just set up a single property because JDBC, the underlying mechanism used to perform database operations, returns the number of rows updated. Thus, i think it is not necessary.
Arthur Ronald F D Garcia
Because of possible side effects. Hibernate has no way of knowing what `setUser()` method really does - you may have some logic there that accesses entity state directly. Additionally, there are all sorts of callbacks Hibernate is contractually obligated to trigged on save (`findDirty()`, for example) that may do the same. Thus entity state is populated immediately upon non-id property access.
ChssPly76
@ChssPly76 You are right, Chss.
Arthur Ronald F D Garcia
A: 

Check this post,the answer that was selected as the correct answer explains everything.

http://stackoverflow.com/questions/608947/hibernate-difference-between-session-get-and-session-load

Rajat