Hibernate Session API

Using Hibernate Native API

Use Hibernate native API to create a transaction and to save data into the database

// SessionFactory is thread safe and can be shared among threads
SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();

Session session = sessionFactory.openSession();
session.beginTransaction();
order = new Order( "Require gift wrap", new Date() );
session.save( order );
session.getTransaction().commit();
session.close();

session = sessionFactory.openSession();
session.beginTransaction();
List results = session.createQuery( "from Order" ).list();
for ( Order result : (List<Order>) results ) {
    ...
}
session.getTransaction().commit();
session.close();

sessionFactory.close();

The exception catching and final block is removed for simplicity

Session session = sessionFactory.openSession();
session.beginTransaction();
order = new Order( "Require gift wrap", new Date() );
session.save( order );
session.getTransaction().commit();
session.close();

The code above

  • Create a new Hibernate session
  • Begin a new transaction
  • Save a new persistence object order to the DB
  • Commit the transaction
  • Close the session

Retrieve data from the DB: retrieve all rows from the table mapped by the persistence class Order

List results = session.createQuery( "from Order" ).list();

The Hibernate session can be used for multiple DB operations (save, query, update) within the same request

Alternatively, use getCurrentSession to create/reuse the session binded to the current thread

sessionFactory.getCurrentSession().beginTransaction();
...
sessionFactory.getCurrentSession().getTransaction().commit();
  • getCurrentSession open a Hibernate session if the current thread does not have one
  • Then it will bind the session to the current thread

Hibernate Transaction Code Skeleton

Skeleton code in handling transaction commit or rollback with exceptions catching

SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();
Session session = sessionFactory.openSession();
try {
   session.beginTransaction();
   ...
   session.getTransaction().commit();
} catch (Exception ex) {
   if (session.getTransaction() != null)
      session.getTransaction().rollback();
   } finally {
      try {
        session.close();
      } catch (Exception ex) {}
   }
}
  • SessionFactory is thread safe. It can be created and retrieved using a simple Singleton pattern
    SessionFactory sessionFactory = MyAppConfiguration().getInstance().getSessionFactory();

Set transaction timeout in Hibernate

session.getTransaction().setTimeout(3);
session.getTransaction().begin();

Create a New Hibernate Factory using a Different Hibernate Configuration File

Create a session factory with a non-default hibernate configuration file

SessionFactory sf = new Configuration().configure("conf2.cfg.xml").buildSessionFactory();

Save a new Hibernate Persistent Entity Object

Save a Hibernate entity using save

Order order = new Order("Require gift wrap", new Date()) ;
order.setCcomment("Require separate gift wrap");
Long primaryKey = (Long) session.save(order);

To avoid non NULL constraint violation, save objects reference by other objects first. For example, save an order before the order's items.

Save a Hibernate entity using persist

Order order = new Order("Require gift wrap", new Date()) ;
order.setCcomment("Require separate gift wrap");


session.persist(order);
  • persist may delay the save later until the transaction is flushed. Hence, the call does not return the primary key

Load a Hibernate Persistence Entity Object

Order o1 = (Order) session.load(Order.class, new Long(233));

Order o2 = new Order();
session.load( o2, new Long(245) );

If the data may not exist in the DB

Order order = (Order) session.get(Order.class, id);
if (order==null) {
    order = new Order();
    session.save(order);
}

Reload data from the DB

Order o1 = (Order) session.load(Order.class, new Long(233));
...
session.refresh(order);

Use SELECT FOR UPDATE to load the data row

Order order = (Order) session.get(Order.class, id, LockMode.UPGRADE);

Update a Hibernate Persistent Entity

Order order = (Order) session.load( Order.class, new Long(333) );
order.setComment("Urgent");
session.flush();
  • Hibernate flush changed (dirty) data back to the DB

Evict a Hibernate Persistent Entity Object from a session

After the eviction, changes to the object will not be updated

session.evict(order);

Re-attach Hibernate Persistent Entity Object to another session

Hibernate Persistent Entity Object States

Hibernate Object States Description
Transient A Java Entity Object is created but not attached to any session and no data is persisted in DB
Persistent A Java Entity Object is attached to a session and ready to persist for any changes
Detached A persistent becomes detached if the associated session is closed

A Hibernate persistent entity can be updated outside an session but then later re-attached to a session and saved

Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.beginTransaction();

Teacher t = (Teacher) session.load(Teacher.class, aTId);
Student s = (Student) session.load(Student.class, aSId);

session.getTransaction().commit();

t.getStudents().add(s);


Session session2 = HibernateUtil.getSessionFactory().getCurrentSession();
session2.beginTransaction();
session2.update(t); // Reattachment an entity

session2.getTransaction().commit();

Create or update an persistent entity object

anotherSession.saveOrUpdate(order);
  • Save the new data if it not exist
  • Else update the data

Merge a persistent entity object

anotherSession.merge(order);
  • Merge changed data to database

Delete Hibernate Persistent Entity Object

Delete a Hibernate persistent entity

session.delete(order);

Execute Hibernate Query

Hibernate query with a where condition

List orders = session.createQuery(
    "from Order as order where order.total < ?")
    .setDouble(0, price)
    .list();

Hibernate query with table join (Returning all matched rows)

List orders = session.createQuery(
    "select order from Item as item join item.order as order where item.price > ?")
    .setInteger(0, count)
    .list();

Hibernate query with table join

  • uniqueResult returns just one row. If more than one row is matched, throw an exception
    Order order = session.createQuery(
        "select order from Item as item join item.order as order where item.id = ?")
        .setInteger(0, id)
        .uniqueResult();  // Will throw an exception if more than one row return

Hibernate Bind Parameter

Generate a prepared statement using Hibernate with binding variable

Query q = session.createQuery("from Order as order where order.total < ?");
q .setDouble(0, price)

Bind the prepared statement with a name

Query q = session.createQuery("from Order as order where order.total < :value");
q .setDouble("value", price)

Query with an array list in Hibernate

List values = new ArrayList();
values.add(244);
values.add(45);

Query q = session.createQuery("from Order as order where order.id in (:valueList)");
q .setDouble("value", values);

Retrieve Hibernate Results

Iterate Hibernate Results

Iterate the DB rows returned from a Hibernate query

Iterator iterator = session.createQuery("from Order as order where order.total < ?").setDouble(0, price).iterate();
while ( iterator.hasNext() ) {
    Order order = (Order) iterator.next();
    ...
}

Retrieve individual result

Iterator iterator = session.createQuery(
    "select order, item, count(item) from Item as item join item.order as order where item.price > ? group by order")
    .setInteger(0, count).list().iterator();

while ( iterator.hasNext() ) {
    Object[] result = (Object[]) iterator.next();
    Order order = (Order) result[0];
    Item item = (Item) result[1];
    Integer count = (Integer) result[2];
    ....
}

Hibernate Pagination

Setting offset and limit in the Hibernate query

Query q = session.createQuery("from Order order");
q.setFirstResult(10);
q.setMaxResults(20);
List orders = q.list();

Hibernate Scrollable

Scroll through the Result Set of a Hibernate query

Query q = session.createQuery("from Order order");
ScrollableResults result = q.scroll();
if ( result.first() ) {
   ...
   result.next();
}
result.close()

Hibernate Filter

Create a filter to screen out query results

Collection lists = session.createFilter(myCollection, "where this.price = 10").list();

Define a Hibernate Filter Using Annotation

@Entity
@FilterDef(name="minimumLength", parameters=@ParamDef( name="minimumLength", type="integer" ) )
@Filters( {
    @Filter(name="minimumLength", condition=":minLength <= length")
} )
  • Filter can be annotated at the class or the collection returned by a method

To enable the filter in a session

session.enableFilter("minimumLength").setParameter("myFilterParam", new Integer(100));

Read Only Hibernate Persistent Entity Object

Set read only for all Hibernate entity object in a session

Session.setDefaultReadOnly( true );

Set read only for entity objects from a Hibernate query

Query.setReadOnly( true );

Set a Hibernate persistent entity object read only

Order order = ( Order) session.get( Order.class, id );
session.setReadOnly( order, true );

Native SQL queries

Use native SQL in Hibernate query

Object[] result = session.createSQLQuery("SELECT id, title FROM orders").list();
Long id = (Long) result[0]

addScale informs Hibernate the column's type without query the metadata from the DB

Object[] result = session.createSQLQuery("SELECT * FROM orders").list();
 .addScalar("id", Hibernate.LONG)
 .addScalar("title", Hibernate.STRING)

Load data into a Java class

After execute a native SQL< load the entity with the returned results

session.createSQLQuery("SELECT id, name FROM orders").addEntity(Order.class);

session.createSQLQuery("SELECT * FROM orders").addEntity(Order.class);

With Association in Join Table

session.createSQLQuery("SELECT o.id, i.id FROM ORDERS o, ITEMS i WHERE o.id = i.o_id")
 .addEntity("order", Order.class)
 .addJoin("order.items");
  • addEntity("order" ... add an alias "order" used later in addJoin

Load into multiple Entity Objects

session.createSQLQuery("SELECT o.*, i.* FROM ORDERS o, ITEMS i WHERE o.id = i.o_id")
 .addEntity("order", Order.class)
 .addEntity("item", Item.class);

With bind parameter

Query q = session.createSQLQuery("SELECT id as {o.id}, price as {i.price} FROM ORDERS o, ITEMS i WHERE o.id=? AND o.id = i.o_id")
 .addEntity("order", Order.class)
 .addEntity("item", Item.class);
q.setString(0, new Long(44));

Hibernate Externalize SQL Query

@Entity
@NamedQuery(name="order.specialorder", query="select order from Order o where o.special = 1")
public class Order {
    ...
}

public class OrderManager {
    List<Order> getSpecialOrder() {
        Query q = session.getNamedQuery("night.specialorder");
        ...
    }
    ...
}

Hibernate Batch Process

Enable batch_size to 10-50 for Hibernate Configuration

  • To reduce memory consumption and performance
    hibernate.jdbc.batch_size 20

Hibernate Batch Insert

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

for ( int i=0; i<10000; i++ ) {
    Order order = new Order(.....);
    session.save(customer);
    if ( i % 20 == 0 ) { // Should be the same as batch size
        session.flush();
        session.clear();
    }
}

tx.commit();
session.close();

Hibernate Criteria

Criteria allows a developer a query condition programmatic

Criteria criteria = session.createCriteria(Order.class);
criteria.setMaxResults(10);
List orders = criteria.list();
List orders = session.createCriteria(Order.class)
    .add( Restrictions.in( "id", new Long[] { 123, 56, 236 } ) )
    .add( Restrictions.or()
        .add( Restrictions.isNull("coupon") )
        .add( Restrictions.eq("count", new Integer(5) ) )
    ) )
    .addOrder( Order.asc("id") )
    .list();
List orders = sess.createCriteria(Order.class)
    .add( Restrictions.in("id", new Long[] { 123, 56, 236 } ) )
    .createCriteria("items")
        .add( Restrictions.like("title", "Sale%") )
    .list();