Now that ColdFusion 9 is in public beta, I wanted to write some
articles explaining how Hibernate is actually working under the hood of
the nice ORM integration we now have. Like all powerful tools, they
can do a great many things – but only if you really understand how they
work. Otherwise, they are potential for disaster if you don't know
what you are doing.
The first thing we need to cover is the concept of Hibernate Sessions,
which has been nicely hidden away from ColdFusion developers by the
Adobe Engineering team, but is still something that you need to really
understand to be able to leverage Hibernate in CF9 properly. (At least
First things first – don't confuse this with ColdFusion Sessions, or
any sort of browser session. Hibernate is built as a generic solution
to ORM, so it has no specific ties to web state. A Hibernate Session
is a lightweight object that is used to delineate when Hibernate is
meant to start working, and when it is meant to stop, which is often
referred to as a unit of work. This may span several transactions and/or INSERT, UPDATE, DELETE and SELECT statements as the Session gets used.
This is very much like the start and stop of a conversation, we say
hello at the beginning, and say goodbye at the end, and whatever we
need to discuss goes on in between, except we just tell the Session to open() and close(), rather than "hello" and "goodbye".
Actual Hibernate Java code would look something like this:
//open the session from the SessionFactory (which is where sessions come from)
Session session = sessionFactory.openSession();
//get fred, our caveman
Caveman fred = session.get("Caveman", 2);
//change his age to 32
//close the session, which will update fred.
I'm not going to get into where the SessionFactory comes from, as all you really need to know is: it's where Hibernate Sessions come from.
So what we are doing here is:
- opening a Session, i.e. we tell Hibernate 'Hi', which starts our conversation.
- Tell Hibernate to retrieve our Caveman fred, through our session.
- We change the age of fred to 32.
- We close our session, and say 'GoodBye' to Hibernate for now.
There are several things that happen here that are worth noting at this point, even in this relatively simple piece of code.
The first is, by doing session.get("Caveman", 2), we have effectively told our Session to track this object, and make note of any changes that happen to it.
We have also cached a copy of fred in the Session itself, so that if we were to attempt to retrieve fred again, we would get the same copy. This is both for performance, and also so that the Hibernate Session only has to deal with one object that represents the data behind fred, which will be a fairly important concept as we continue in this article series.
Since our Session is tracking fred, any change we make to fred will be persisted to the database when we close our Session. In that way, Hibernate is quite transparent in the way it implements persistence.
It should also be noted at this point: Unless you specify otherwise,
Hibernate will only run INSERT, UPDATE and DELETE when the session is
closed, generally as a batch. This is so that, for example, multiple
changes happen to fred during the length of our Session,
there only needs to be one UPDATE statement when we are finished. This
is an important thing to note, as it is possible to get confused as to
why your changes to your objects aren't appearing in your database during your Session, but do appear afterwards.
Hibernate Sessions and Web Applications
In web applications, it is usual to manage Hibernate Sessions by
opening one up at the beginning of a HTTP request, and then closing at
the end of the request. The length of a single HTTP request is a good
size to carry on a nice conversation with Hibernate.
Strangely enough, this is exactly what ColdFusion is doing for you behind the scenes. It starts a Hibernate Session
when your request starts, and ties it to that particular request, and
then closes it at the end of the request. (It is quite likely that the
Session actually only gets created when first requested, but for the
sake of argument it is easier to explain it as it gets opened at the
start of the request)
From there, each of the ORM functions, EntityLoad, EntitySave, EntityDelete, etc, all interact with that Session that exists behind the scenes, for that request.
This means that changes to your objects will also not be persisted to your database, until the end of your ColdFusion request, as that is when the Hibernate Session is closed. In later articles, I'm going to cover some ways this can cause some trouble, and how to work around them.
You are actually able to flush the Session, which
forces it to persist any changes to the database right then and there,
and not wait until the end of the request, which can sometimes be very
To do this in Java, you could go:
But in ColdFusion you write:
UPDATE: You can read more about Session Flushing here, which outlines that there are times in which Hibernate will flush a Session in the middle of Session, however, there is often no guarantee except in specific circumstances.
It's also interesting to note you have direct access to the Hibernate Session if you so desire through ORMGetSession(), which gives you access to that request's Hibernate Session object, so you can interact with it directly.
There is much more to Hibernate Sessions and how they relate to the
objects that they manage, but this will give us a good start to build
upon for now.
You can read more about ColdFusion and Hibernate Sessions in the documentation Hibernate Session Management.