Hibernate : Object States and HQL

Hibernate defines and supports the following object states:

  • Transient – an object is transient if it has just been instantiated using the new operator, and it is not associated with a Hibernate Session. It has no persistent representation in the database and no identifier value has been assigned. Transient instances will be destroyed by the garbage collector if the application does not hold a reference anymore.
  • Persistent – a persistent instance has a representation in the database and an identifier value. It might just have been saved or loaded, however, it is by definition in the scope of a Session. Hibernate will detect any changes made to an object in persistent state and synchronize the state with the database when the unit of work completes. Developers do not execute manual UPDATE statements, or DELETE statements when an object should be made transient.
  • Detached – a detached instance is an object that has been persistent, but its Session has been closed. The reference to the object is still valid, of course, and the detached instance might even be modified in this state. A detached instance can be reattached to a new Session at a later point in time, making it (and all the modifications) persistent again.

Lets us see this using our Employee entitiy.


package com.hibernate.objectStates;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Employee {

@Id
 @GeneratedValue(strategy = GenerationType.AUTO)
 private int id;
 private String name;

 public int getId() {
 return id;
 }

public void setId(int id) {
 this.id = id;
 }

public String getName() {
 return name;
 }

public void setName(String name) {
 this.name = name;
 }
}

hibernate.cfg.xml :


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
 "-//Hibernate/Hibernate Configuration DTD//EN"
 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
 <session-factory>
 <!-- Database connection settings -->
 <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
 <property name="connection.url">jdbc:mysql://localhost:3306/hibernateDB</property>
 <property name="connection.username">root</property>
 <property name="connection.password">admin</property>
 <!-- JDBC connection pool (use the built-in) -->
 <property name="connection.pool_size">1</property>
 <!-- SQL dialect -->
 <property name="dialect">org.hibernate.dialect.MySQLDialect</property>
 <!-- Disable the second-level cache -->
 <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
 <!-- Echo all executed SQL to stdout -->
 <property name="show_sql">true</property>
 <!-- Drop and re-create the database schema on startup -->
 <property name="hbm2ddl.auto">update</property>
 <!-- Names the annotated entity class -->
 <mapping class="com.hibernate.objectStates.Employee"></mapping>
 </session-factory>
</hibernate-configuration>

HibernateObjectStatesTest.java:


package com.hibernate.objectStates;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateObjectStatesTest {

public static void main(String[] args) {
System.out.println("HibernateTest");
Employee aEmployee = new Employee();
aEmployee.setName("Employee Name1");
// point1
SessionFactory sessionFactory = new Configuration().configure(
"/com/hibernate/objectStates/hibernate.cfg.xml")
.buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(aEmployee);
// point2
session.getTransaction().commit();
session.close();
// point3
}

}

Output:


Hibernate: insert into Employee (Name) values (?)

Till point1 the employee object is transient, i.e hibernate doesnt know about it even though its a Entity object. Only after we pass the object to the session via session.save() – point2, the object becomes persistent and hibernate keeps track of it. After the session is closed – point3, the object is now in a detached state and hibernate no longer keeps track of it. Lets take an example to know what we mean when we say that hibernate keeps a track of it. HibernateObjectStatesTest.java:


package com.hibernate.objectStates;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateObjectStatesTest {

public static void main(String[] args) {
System.out.println("HibernateTest");
Employee aEmployee = new Employee();
aEmployee.setName("Employee Name1");
// point1
SessionFactory sessionFactory = new Configuration().configure(
"/com/hibernate/objectStates/hibernate.cfg.xml")
.buildSessionFactory();
Session session = sessionFactory.openSession();
session.beginTransaction();
session.save(aEmployee);

aEmployee.setName("Employee Update 1");
aEmployee.setName("Employee Update 2");
// point2
session.getTransaction().commit();
session.close();
// point3
aEmployee.setName("Employee Update 3");
}

}

Output:


Hibernate: insert into Employee (name) values (?)
Hibernate: update Employee set name=? where id=?

Notice that it inserted the object first and then automatically updated the object when the .setName() method was called. Also notice, that only one update query was fired, that is because, hibernate intelligently keeps track of the object attributes, and will update only the last change on that attribute of the object. Once the session is closed, the object gets detached and hibernate doesnot track it anymmore.

Its not necessary to use session.save() method to make a object persistent. You can directly get the object from the the session using session.get().  Also, when you are using session.delete() method on an entity you are moving it back to the transient state.

HQL

Hibernate uses a powerful query language (HQL) that is similar in appearance to SQL. Compared with SQL, however, HQL is fully object-oriented and understands notions like inheritance, polymorphism and association. The main difference between is HQL uses class name instead of table name, and property names instead of column name.

Before proceeding , populate you Employee Table in the database.

DbTableBeforeHql

Our test class:


package com.hibernate.hql;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateHqlTest {

    public static void main(String[] args) {
                
        SessionFactory sessionFactory = new Configuration().configure(
                "/com/hibernate/objectStates/hibernate.cfg.xml")
                .buildSessionFactory();
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        
        Query query1=session.createQuery("from Employee");
        List<Employee> list1=query1.list();
        System.out.println("list1 size="+list1.size());
        
        Query query2=session.createQuery("from Employee where id>6");
        List<Employee> list2=query2.list();
        System.out.println("list2 size="+list2.size());
        
    
        session.getTransaction().commit();
        session.close();
        
    }

}

 

Output:


Hibernate: select employee0_.id as id1_0_, employee0_.name as name2_0_ from Employee employee0_
list1 size=10
Hibernate: select employee0_.id as id1_0_, employee0_.name as name2_0_ from Employee employee0_ where employee0_.id>6
list2 size=4

 

We created a query using session.createQuery() method. Notice that we have to used class name instead of table name and attribute name instead of column name.

If you want to use parametrized type query you could try as follows:


Hibernate: select employee0_.id as id1_0_, employee0_.name as name2_0_ from Employee employee0_ where employee0_.id>?
list3 size=4
Hibernate: select employee0_.id as id1_0_, employee0_.name as name2_0_ from Employee employee0_ where employee0_.id>?
list4 size=4

 

If you want your result fetched step by step, like in pagination :


Query query5=session.createQuery("from Employee");
        query5.setFirstResult(3);
        query5.setMaxResults(4);
        List<Employee> list5=query5.list();
        System.out.println("list5 size="+list5.size());
        for (Employee employee : list5) {
            System.out.println(employee.getName());
        }

 

Output:


ibernate: select employee0_.id as id1_0_, employee0_.name as name2_0_ from Employee employee0_ limit ?, ?
list5 size=4
Employee Name4
Employee Name5
Employee Name6
Employee Name7

 

In order to update a row:


Query query6=session.createQuery("update Employee set name = :newName" +
                " where id = :myId");
        query6.setInteger("myId", 6);
        query6.setString("newName", "New Employee Name");
        int result = query6.executeUpdate();
        System.out.println("result="+result);

 

Output:


Hibernate: update Employee set name=? where id=?
result=1

The query.executeUpdate() will return how many number of record has been inserted, updated or deleted.

 

Advertisements

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: