Getting the Persistence Context Picture (Part II)The first article of this series  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 APIsAll 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
SessionFactoryclass 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
SessionFactoryinstances, 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: The Grails application's session-factoy is than injected by dependency injection since every Grails service class is a Spring-managed component. Other components include controllers, domain-classes and custom beans (either in
beans.xml, other bean definition XMLs or annotated Groovy/Java classes). A Grails application's session-factory is set-up by the
HibernatePluginSupportclass, 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. Btw, if we would have to create a session-factory within a plain Groovy application, it wouldn't get much harder: The
Configurationclass can be used to configure a session-factory programatically, other options would be to use a properties-file or an XML file (named
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
The Persistence-Context Pattern or
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
Sessioninterface provides a bunch of methods letting the application infrastructure interact with the persistence context: Whenever e.g. a query is created by one of the querying methods, all objects which are retrieved are automatically linked to the session. For each attached (Hibernate term for "linked") object, the session holds a reference and meta-data about it. Whenever a transient Groovy object is saved, it gets automatically attached to the current session. Notice that this is a unidirectional relationship: the session knows everything whereas the attached object instances don't know anything about being linked to a session.
Lazy and Eager LoadingIn 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 class
Areferences another persistent class
Ais 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. Lazy loading does not hurt as long as objects are attached to a persistence context. Although, if the persistence context is closed, there is no way to navigate over a lazy loaded relationship. Whenever application code needs to access lazy relationships this leads to a lazy loading exceptions.
Obtaining a SessionPer default, a session instance can be obtained using a session-factory instance: As it is the case with the code sample above, most of the time application code is working in a transactional context, that is, the current method is executed within a single transaction. Therefore, it is a common idiom to open a transaction with the beginning of a session, although this is not enforced by Hibernate's API. If we would not use transaction boundaries, we could just omit the method call to
beginTransaction: You need to be careful in this scenario. If Hibernate obtains a JDBC connection, it automatically turns autocommit mode off by setting
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 GrailsAs 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 a
HibernateTemplateis 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. When invoking the static
findBydynamic finder method, the following code is executed: As can be seen, Grails internally does nothing more than creating a Spring
HibernateTemplateand in its
doInHibernatecallback, creates a plain Hibernate
Criteriaobject 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
Session FlushingSince 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
- before a query is executed
session.flush()is called explicitly
FlushMode.NEVERin 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
OpenSessionInViewinterception 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.NEVERafter 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
transactionalor is annotated with
@Transactional): When doing integration tests on Grails classes, you need to remind these point-cuts where sessions get flushed. To make things even more complicated, there is one additional thing that is different in integration tests: each integration test method runs in its own transaction, which at the end is rollbacked by Grails testing classes. E.g. if testing a controller's save method, chances are you can't find an SQL INSERT or UPDATE statement in database logs. This is the intended behavior, but it causes confusion if bugs dealing with persistence issues need to be reproduced by test-cases. If it is about transactions in integration tests, there is a way to deactivate transaction boundaries there:
SummaryIn this article we took a look at how Grails and GORM handles Hibernate's basic APIs: the
Session. The next article in this series will deal with more advanced features: GORM in batch-jobs and conversational state management.