Hibernate : Other Important methods

Difference between get and load method

  • Main difference between get() vs load method is that get() involves database hit if object doesn’t exists in Session Cache and returns a fully initialized object which may involve several database call while load method can return proxy in place and only initialize the object or hit the database if any method other than getId() is called on persistent or entity object. This lazy initialization can save couple of database round-trip which result in better performance.
    Session session1 = sessionFactory.openSession();
     session1.beginTransaction();
     Employee employee1=(Employee) session1.get(Employee.class, 2);
     System.out.println("get call finished");
     session1.getTransaction().commit();
     session1.close();
    
     Session session2 = sessionFactory.openSession();
     session2.beginTransaction();
     System.out.println("calling load");
     Employee employee2=(Employee) session2.load(Employee.class, 2);
     session2.getTransaction().commit();
     session2.close();
    

    Output:

    Hibernate: select employee0_.id as id1_0_0_, employee0_.name as name2_0_0_ from Employee employee0_ where employee0_.id=?
    get call finished
    calling load
    

    As you can see get() went to DB to fetch while load didnt. If only getters is called , load will first search if the its in cache, if not it will hit DB

  • get method of Hibernate Session class returns null if object is not found in cache as well as on database while load() method throws ObjectNotFoundException if object is not found on cache as well as on database but never return null.
    Session session4 = sessionFactory.openSession();
     session4.beginTransaction();
     Employee employee4=(Employee) session4.get(Employee.class, 123);
     System.out.println("get call finished");
     System.out.println(employee4);
     session4.getTransaction().commit();
     session4.close();
    
     Session session5 = sessionFactory.openSession();
     session5.beginTransaction();
     System.out.println("calling load");
     Employee employee5=(Employee) session5.load(Employee.class, 123);
     System.out.println("load call finished");
     System.out.println(employee5);
     session5.getTransaction().commit();
     session5.close();
    

    Output:

    get call finished
    null
    calling load
    load call finished
    Hibernate: select employee0_.id as id1_0_0_, employee0_.name as name2_0_0_ from Employee employee0_ where employee0_.id=?
    Exception in thread "main" org.hibernate.ObjectNotFoundException: No row with the given identifier exists:
    

Difference between update() and merge() method

Both update() and merge() methods in hibernate are used to convert the object which is in detached state into persistence state. But there is a difference. Let us check this by an example:


Session session1 = sessionFactory.openSession();
 session1.beginTransaction();
 Employee employee1=(Employee) session1.get(Employee.class, 4);
 session1.getTransaction().commit();
 session1.close();
 System.out.println(employee1.getId());
 employee1.setName("My New updated Name "+(new Random()).nextInt(100));
 System.out.println(employee1.getName());

 Session session2 = sessionFactory.openSession();
 session2.beginTransaction();
 Employee employee2=(Employee) session2.get(Employee.class, 4);
 System.out.println(employee2.getName());
 session2.update(employee1);
 session2.getTransaction().commit();
 session2.close();

Output:


Hibernate: select employee0_.id as id1_0_0_, employee0_.name as name2_0_0_ from Employee employee0_ where employee0_.id=?
4
My New updated Name 84
Hibernate: select employee0_.id as id1_0_0_, employee0_.name as name2_0_0_ from Employee employee0_ where employee0_.id=?
Employee Name4
Exception in thread "main" org.hibernate.NonUniqueObjectException: A different object with the same identifier value was already associated with the session : [com.hibernate.methods.Employee#4]

To understand the cause of this exception, it’s important to understand detached objects and what happens when you call saveOrUpdate() (or just update()) on a detached object.
When we close an individual Hibernate Session, the persistent objects we are working with are detached. This means the data is still in the application’s memory, but Hibernate is no longer responsible for tracking changes to the objects. If we then modify our detached object and want to update it, we have to re-attach the object. During that reattachment process, Hibernate will check to see if there are any other copies of the same object. If it finds any, it has to tell us it doesn’t know what the “real” copy is any more. Perhaps other changes were made to those other copies that we expect to be saved, but Hibernate doesn’t know about them, because it wasn’t managing them at the time. Rather than save possibly bad data, Hibernate tells us about the problem via the NonUniqueObjectException.

In Hibernate 3, we have merge() (in Hibernate 2, use saveOrUpdateCopy()). This method will force Hibernate to copy any changes from other detached instances onto the instance you want to save, and thus merges all the changes in memory before the save.


Session session3 = sessionFactory.openSession();
 session3.beginTransaction();
 Employee employee3=(Employee) session3.get(Employee.class, 6);
 session3.getTransaction().commit();
 session3.close();
 System.out.println(employee3.getId());
 employee3.setName("My New updated Name "+(new Random()).nextInt(100));
 System.out.println(employee3.getName());

 Session session4 = sessionFactory.openSession();
 session4.beginTransaction();
 Employee employee4=(Employee) session4.get(Employee.class,6);
 System.out.println(employee4.getName());
 Employee employee5=(Employee) session4.merge(employee3);
 System.out.println(employee5.getName());
System.out.println(employee3==employee5);
 session4.getTransaction().commit();
 session4.close();

Output:

Hibernate: select employee0_.id as id1_0_0_, employee0_.name as name2_0_0_ from Employee employee0_ where employee0_.id=?
6
My New updated Name 96
Hibernate: select employee0_.id as id1_0_0_, employee0_.name as name2_0_0_ from Employee employee0_ where employee0_.id=?
Employee Name6
My New updated Name 96
false
Hibernate: update Employee set name=? where id=?

It’s important to note that merge returns a reference to the newly updated version of the instance. It isn’t reattaching employee3 to the Session. If you test for instance equality (employee3== employee5), you’ll find it returns false in this case. You will probably want to work with employee5 from this point forward.

So Another difference – update() return type is void and reattaches the same object to the session whereas merge() return type is the reference to the newly updated version of the instance.

Difference between openSession() and getCurrentSession()

openSession() will return a new session object on every call. We can use this method when we decided to manage the Session our self. It does not try to store or pull the session from the current context. If you use this method  you need to flush() and close() the session. It does not flush and close() automatically.

getCurrentSession()creates a brand new session if one does not exist or uses an existing one if one already exists. This session will automatically closed and flushed when the when the transaction ends(commit or rollback). using the getCurrentSession () requires in hibernate.cfg.xml file add the following configuration:

  • * If you are using a local transaction (jdbc Affairs)
    <property name=”hibernate.current_session_context_class”> thread </ property>
  •  If you are using the global transaction (JTA transaction)
    <property name=”hibernate.current_session_context_class”> jta </ property>

session.flush()

Flushing the session forces Hibernate to synchronize the in-memory state of the Session with the database, i.e run the query. Let see this with an example:


Session session1 = sessionFactory.openSession();
 session1.beginTransaction();
 Employee employee1=(Employee) session1.get(Employee.class, 1);
 System.out.println("employee1 Name=="+employee1.getName());
 employee1.setName("Update This Name");
 System.out.println("before commit");
 session1.getTransaction().commit();
 session1.close();
 System.out.println("------------------");
 Session session2 = sessionFactory.openSession();
 session2.beginTransaction();
 Employee employee2=(Employee) session2.get(Employee.class, 1);
 System.out.println("employee2 Name=="+employee2.getName());
 employee2.setName("Update This Name again");
 session2.flush();
 System.out.println("before commit");
 session2.getTransaction().commit();
 session2.close(); 

Output:


Hibernate: select employee0_.id as id1_0_0_, employee0_.name as name2_0_0_ from Employee employee0_ where employee0_.id=?
employee1 Name==Update This Name again
before commit
Hibernate: update Employee set name=? where id=?
------------------
Hibernate: select employee0_.id as id1_0_0_, employee0_.name as name2_0_0_ from Employee employee0_ where employee0_.id=?
employee2 Name==Update This Name
Hibernate: update Employee set name=? where id=?
before commit

As you can see, in the first case, the update staement ran after commit while in the second case where we used flush, the update starement ran before commit.

Flushing the Session simply gets the data that is currently in the session synchronized with what is in the database. However, just because you have flushed, doesn’t mean the data can’t be rolled back, i.e data is still not commited.

By default, Hibernate will flush changes automatically for you:

  • before some query executions
  • when a transaction is committed

Allowing to explicitly flush the Session gives finer control that may be required in some circumstances (to get an ID assigned, to control the size of the Session etc.)

Also, session.close() will not call session.flush() before closing the session.

session.referesh(Object object)

Re-read the state of the given instance from the underlying database. It is inadvisable to use this to implement long-running sessions that span many business tasks. This method is, however, useful in certain special circumstances. For example

  • where a database trigger alters the object state upon insert or update
  • after executing direct SQL (eg. a mass update) in the same session

session.referesh(Object object,LockMode lockMode) – Depricated

Obtain the specified lock level upon the given object. This may be used to perform a version check (LockMode.READ), to upgrade to a pessimistic lock (LockMode.PESSIMISTIC_WRITE), or to simply reassociate a transient instance with a session (LockMode.NONE).
It allows your application to reattach the object to the session. It doesn’t check or update the database as it assumes that the
database is in sync with the detached object.

 

HibernateStates

Difference between sorted and ordered collection in hibernate?

A sorted collection is sorted in memory by using java comparator while ordered collection uses db order by clause for ordereing. For large data sets its better to use ordered collection to avoid any OutOfMemoryError.

Every Hibernate Entity class must contain a no-arg constructor, because Hibernate framework creats instance using the reflection API.

Session factory is Thread safe.

Sessions are not thread safe.

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: