Written on
Getting the Persistence Context Picture (Part II)
The first article of this series [0] took a look at the basic patterns found in todays persistence frameworks. In this article we will have a look at how Hibernate APIs relate to those patterns and how Hibernate is utilized in Grails.A Closer Look at Hibernate's Persistence Context APIs
All data creation, modification and altering has to be done in a persistence context. A persistence context is a concrete software element that maintains a list of all object modifications and, in a nutshell, at the end of the persistence context life-time or business transaction synchronizes them with the current database state. When developing with a modern web framework - as Grails is - it is most likely you don't even have to care about opening a persistence context or closing it, or even know about how this could be done. But as application complexity raises, you have to know Hibernate's persistence context APIs and understand how they are integrated within the web application framework of your choice. Let us take a look at the most import APIs and how they correspond to persistence patterns.The Registry Pattern or org.hibernate.SessionFactory
The SessionFactory
class implements the registry pattern. A registry is used by the infrastructure-layer to obtain a reference to the current persistence context, or to create a new one if not found in the current context.
Usually, as noted in SessionFactory's Java documentation, a session-factory refers to a single persistence provider. Most of the time, application need just a single session-factory. Indeed, if an application wanted to work across multiple databases, it would have to maintain multiple SessionFactory
instances, one for each database.
Imagine a session-factory to be a configuration hub - it is the place where all configuration settings are read and used for constructing persistence contexts.
In a Grails application, the application's session-factory can be easily obtained by declaring a property of type org.hibernate.SessionFactory
:
class SomeService {
SessionFactory sessionFactory
void myServiceMethod() {
def session = sessionFactory.getCurrentSession()
// ...
}
}
beans.groovy
, beans.xml
, other bean definition XMLs or annotated Groovy/Java classes).
A Grails application's session-factory is set-up by the HibernatePluginSupport
class, which is a utility class used by Grails hibernate plugin. When taking a look at the source code you'll find out that the code uses Grails Spring builder DSL to declare a ConfigurableLocalSessionFactoryBean
. This type of bean is usually used in Spring applications to create a Hibernate session-factory instance during application bootstrap and to keep track of it during the entire life-time of the application-context.
//...
sessionFactory(ConfigurableLocalSessionFactoryBean) {
dataSource = dataSource
// ...
hibernateProperties = hibernateProperties
lobHandler = lobHandlerDetector
}
//...
def configuration = new Configuration()
.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQLInnoDBDialect")
.setProperty("hibernate.connection.datasource", "java:comp/env/jdbc/test")
.setProperty("hibernate.order_updates", "true")
// ...
def sessionFactory = configuration.buildSessionFactory()
Configuration
class can be used to configure a session-factory programatically, other options would be to use a properties-file or an XML file (named hibernate.properties
or hibernate.cfg.xml
). If using any of the file-based configurations, take care your configuration file can be loaded by the current class-loader, therefore put it in the class-path's root directory.
Grails configuration of Hibernate's session-factory is pretty much hided from application developers. In order to provide a custom hibernate.cfg.xml
, just put it in the grails-app/conf/hibernate
folder.
The Persistence-Context Pattern or org.hibernate.Session
The Session builds the heart of Hibernate: it resembles a persistence context. Thus, whenever the application needs to access object-mapping functionality in either form, it needs to work with an instance of type Session
.
The Session
interface provides a bunch of methods letting the application infrastructure interact with the persistence context:
// ...
public Query createQuery(String queryString) throws HibernateException;
public SQLQuery createSQLQuery(String queryString) throws HibernateException;
public Query createFilter(Object collection, String queryString) throws HibernateException;
public Query getNamedQuery(String queryName) throws HibernateException;
public void clear();
public Object get(Class clazz, Serializable id) throws HibernateException;
public void setReadOnly(Object entity, boolean readOnly);
public void doWork(Work work) throws HibernateException;
Connection disconnect() throws HibernateException;
void reconnect() throws HibernateException;
void reconnect(Connection connection) throws HibernateException;
// ...
Lazy and Eager Loading
In regard to attaching objects to the current session, you need to know the concepts of lazy and eager loading of object relationships. Whenever a persistent classA
references another persistent class B
, A
is said to have a relationship with B
. Object relationships are mapped either with foreign keys or relationship tables in the underlying database schema. As default, Hibernate uses a lazy loading approach: whenever a root object with relations to other objects is loaded, the related objects are not loaded. The other approach would be eager loading, where the object relationship is loaded with the root object.

Obtaining a Session
Per default, a session instance can be obtained using a session-factory instance:
def session = sessionFactory.openSession()
def tx = session.beginTransaction()
// ... work with the session
tx.commit()
session.close()
beginTransaction
:
def session = sessionFactory.openSession()
// ... work with the session
session.close()
jdbcConnection.setAutoCommit(false)
. Indeed, this is the JDBC way to tell the database to start a new transaction. However, how the database driver reacts on pending transactions is not specified, an application runs into undefined behavior.
General Session-Handling in Grails
As manual session handling can get tricky, web frameworks like Grails hide most of these problems. The Grails' Object Relational Mapping (GORM) layer is a thin layer above Hibernate 3. Grails uses this layer to enrich domain classes with a lot of DAO like functionality. E.g. to each domain class so-called dynamic finders are added, which most of the time completely replace the need for data access objects (DAOs). Handling of Hibernate sessions is mainly hidden by GORM which internally uses Spring's Hibernate integration and Hibernate. Whenever executing a GORM query Grails internally creates aHibernateTemplate
. A HibernateTemplate
is a neat way to get defined access to a Hibernate session. It completely hides getting the session-factory and retrieving a session. Clients only need to implement callback methods, which are than called on execution of that template. Let's take a look how such templates are used when executing e.g. a dynamic finder method like findBy
.
class SomeController {
def myAction() {
def User user = User.findByLogin(params.id)
// ...
}
}
findBy
dynamic finder method, the following code is executed:
// ...
return super.getHibernateTemplate().execute( new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
Criteria crit = getCriteria(session, additionalCriteria, clazz);
// ... do some criteria building
final List list = crit.list();
if(!list.isEmpty()) {
return GrailsHibernateUtil.unwrapIfProxy(list.get(0));
}
return null;
}
});
HibernateTemplate
and in its doInHibernate
callback, creates a plain Hibernate Criteria
object which is used to specify object queries. Spring hides the code of finding the current session and setting properties according to the current program context, GORM adds this functionality and does all Groovy meta-programming stuff (adding static methods etc. to the domain's meta class).
The same is true for saving domain objects using GORM's save
method:
protected Object performSave(final Object target, final boolean flush) {
HibernateTemplate ht = getHibernateTemplate();
return ht.execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
session.saveOrUpdate(target);
if(flush) {
// ...
getHibernateTemplate().flush();
// ...
}
return target;
}
});
}
Session Flushing
Since a session spans a business transaction (remember, not the same as a technical transaction) it might be left open by the infrastructure-layer over several user interaction requests. The application needs to ensure that a session is closed and its state synchronized with the database at some time, which is called flushing a session. As we have already seen in the Grails source code above, flushing is mainly handled by the web framework, but programmers should know the point-cuts where it actually happens:- whenever a
Transaction
gets committed - before a query is executed
- if
session.flush()
is called explicitly
def session = sessionFactory.openSession()
session.setFlushMode(FlushMode.NEVER)
FlushMode.NEVER
in this case means that session flushing is deactivated, only explicit calls to session.flush()
triggers it.
In Grails, session flushing is done after each controller call, due to Spring's OpenSessionInView
interception mechanism. In order to access lazy-loaded properties in GSP pages, the session is not closed completely after a controller's method call but after response rendering is done. Therefore, it sets session flushing mode to FlushMode.NEVER
after a controller method call to avoid DB modifications caused by GSP page code.
Another place where sessions get flushed, is at the end of each service method call (as long as the service is marked as being transactional
or is annotated with @Transactional
):
class SomeService {
static transactional = true
def someMethod() {
// ... transactional code
}
}
class SomeService {
@Transactional
def someMethod() {
// ... transactional code
}
}
class SomeTest extends GrailsTestCase {
static transactional = false
@Test
def testWithoutTransactionBoundary() {
// ... transactional code
}
}
Summary
In this article we took a look at how Grails and GORM handles Hibernate's basic APIs: theSessionFactory
and the Session
. The next article in this series will deal with more advanced features: GORM in batch-jobs and conversational state management.