Compound Theory

v2.0

Categories

  1. Transfer
  2. ColdFusion
  3. JRuby
  4. Java
  5. ColdSpring
  6. Squabble
  7. JavaLoader
  8. ColdDoc
  9. 2ddu
  10. AsyncHTTP
  11. OO Analysis and Design
  12. Flex
  13. Railo
  14. XML / XSL
  15. Hibernate
  16. ColdFusion Builder
  17. Fall
  18. Ubuntu
  19. XHTML / CSS
  20. Eclipse
  21. Git
  22. Oracle Database
  23. Usability / UI Design
  24. webDU
  25. cf.Objective()
  26. LWJGL
  27. cf.Objective(ANZ)
  28. Captcha
  29. MAX
  30. Melbourne CFUG
  31. Martial Arts
  32. Random Things
  33. Conduit

Recent Posts

Projects

Recent Comments

12 October 2011 07:55 AM 9 Comments

How I Configure ColdFusion ORM and Why

I’ve been reading quite a few mailing list posts on ColdFusion based ORM, and I find that I’m seeing a lot of repeats on what configuration settings people are generally using when setting up ORM in their Applicaiton.cfc, and why they should use certain settings.

I figured it would be useful if I wrote down how I like to have my base configuration of my Application.cfc in regards to ORM, and also take a step by step look through why I set things up the way I do.  Hopefully this will help out a few people when they first start out with ORM, and are looking at all the different options for ORM in ColdFusion.

<cfscript>
   this.datasource = mydatasource;

   //orm settings
   this.ormEnabled = true;
   this.ormSettings.cfclocation = expandPath("/model");

   this.ormSettings.automanageSession = false;
   this.ormSettings.flushatrequestend = false;

   this.ormSettings.useDBForMapping = false;

   this.ormSettings.autogenmap = false;

   if(isDevEnvironment())
   {
      this.ormSettings.dbcreate = "dropcreate";
      this.ormSettings.sqlscript = expandPath("/import.sql");
   }
</cfscript>

So breaking this down line by line.

this.datasource = "mydatasource";

This isn’t specifically an ORM setting, but I love how in CF9, we can set a default datasource across the application in one place. Also like that ORM picks this up too, although it can be overwritten with ormSettings.

this.ormEnabled = true;

Again, nothing special. We turn on ORM. Without this line, nothing happens.

this.ormSettings.cfclocation = expandPath("/model");

When ORM is enabled, by default, ColdFusion will scan from your web root, looking for any CFC’s that are marked as persistent. As a performance enhancement, it’s useful to tell it specifically what folder to look at.  Also, if you have your components stored in a mapped directory, this is the only way it can be done.

I’ve seen this set a few ways (dot notation, relative paths), and seen a fair few people have issues with this. Personally, I’ve never had an issue when using the expandPath(), so I stick with that as the way to go.

this.ormSettings.automanageSession = false;
this.ormSettings.flushatrequestend = false;

I bundle these two together because they are quite related in what they do. They basically control how the Hibernate session works in ColdFusion ORM. This combination of settings does the following:

For me, this is very, very, very important. The default setting of having these both on for ORM makes doing basic things with ORM very easy, but when you start getting into more complex scenarios, in which issues like object validation or concurrency arise, these default settings can throw some fun Hibernate exceptions on your screen super fast.

By setting the above to false, you have complete control over when a session will flush (only when a transaction commits), and you know it will only be cleared when you request it to be. This makes it a lot easier to manage your Hibernate object states in those more tricky scenarios.

(You can use ormFlush() with the above settings, but please don’t do that. Please use transactions. Your database will thank you.)

this.ormSettings.useDBForMapping = false;

This is primarily a performance setting. By turning this off, it stops ColdFusion from going out to your database and looking at what tables and columns you have and attempting to generate it’s object mappings from there. Personally I can’t stand this functionality, as your DB then drives you model (not an ideal scenario), and also because, if you are using annotations / HBMXML config files, there is absolutely no reason to do this (and I’ve read of people on Oracle having crazy issues with having this enabled by default as well).

this.ormSettings.autogenmap = false;

This setting is most definitely a personal preference thing. When I work with ORM I use the HBMXML mapping files, as every time I use the annotations, I find it doesn’t default the way I would expect/want, or I am looking to use some Hibernate functionality that isn’t exposed through annotations. Then I have to go back and move all my configuration from annotations to a HBMXML file. It’s far easier to me to start with a HBMXL file, and never look back. Since I also have a CFBuilder extension to help generate the stub files, it makes it an easy decision.

Setting autogenmap to false, means that even if someone were to come along and use annotations, they wouldn’t work, so it makes sure I don’t have that "Just this once I’ll do annotations..." thought which inevitably leads me back to rewriting annotations into HBMXML again.

this.ormSettings.dbcreate = "dropcreate";
this.ormSettings.sqlscript = expandPath("/import.sql");

This setting is more for greenfield projects. On legacy projects, I find that they tend to frown on having all their development data dropped, for obvious reasons, and it can be a large project to write an import script for it all.  However, when starting from scratch, it’s really nice to have a clean data set on every reload, especially from a unit testing perspective.

There are many more settings that can be used, that are generally more application specific, such as the SQL dialect, or whether or not you enable the second level cache, but this is generally speaking, the base configuration I start most project from.

13 July 2010 01:15 PM 0 Comments

Adobe MAX Pre-Conference - Getting Started with ColdFusion 9 ORM

Bob Silverberg and I are back at it again, with a one day pre-conference lab at Adobe MAX this year covering an introduction to Object Relational Mapping in ColdFusion 9.

As the description states:
Learn about one of the most compelling new features in Adobe ColdFusion 9 from two seasoned ColdFusion veterans. This release includes the integration of Hibernate, an enterprise-class, Java based ORM. Join us to hear how to get started using ColdFusion 9 ORM features in your next project. Through interactive learning and hands-on labs, we'll start with the basics and work together to add features to an application that takes advantage of the ORM. Then we'll discuss best practices and potential pitfalls, making this an ideal combination of introductory material and tips and tricks.
If you are interested in getting your feet wet with ColdFusion 9 ORM, you can get more information on the MAX pre-conference page .

Hope to see you there!
07 April 2010 09:58 AM 1 Comment

ColdFusion ORM Training + Java Persistance with Hibernate = Awesome!

Like Tyra Banks giving away Vaseline to her entire audience, the attendees of Bob Silverberg's and I's ColdFusion 9 ORM Training, that we are running at cf.Objective(), ever student who attends our training will also get a copy of:

Java Persistence with Hibernate!

You get a book! You get a book! You get a book! Yoouuuuuu get a Booooooooook!!!!

While this is a Java book, and hey, we all write ColdFusion, it is one of the books to read on utilising Hibernate within your applications. Reading this book will give you a huge insight into what ColdFusion is doing under the covers, which will help out a great deal when building applications with ColdFusion 9.

So not only do you get some great training from Bob and I, you also get a fantastic reference to take home with you as well!

If that doesn't push you over the edge to come join us, I don't know what will.

(Ordering now does not provide you with a free set of steak knives, but it will make Bob and I very happy)

cf.Objective() ColdFusion 9 ORM Training

I believe it is time for some shameless self promotion!

If you were looking for more information on the ColdFusion 9 Object Relational Mapping Training that the venerable Bob Silverberg and I are putting on at cf.Objective() next April, we have just fleshed out the content section of our site to include a detailed outline of the topics that we will be covering during the training program.

You'll know Bob from his blogging at http://www.silverwareconsulting.com/, on a variety of all too clever stuff, including CF9 ORM, Git, Unit Testing, and ValidateThis - his own open source validation framework.  He's also an all-around nice guy

You'll see that we cover a variety of topics with ColdFusion 9 ORM that will allow you to hit the ground running once you have completed our training, and it will be taught in a clear, step by step manner that will leave you wondering why you ever thought the term "Object Relational Mapper" sounded so scary and complicated.

So if you are keen on expanding your skill-set with ColdFusion 9, and specifically with its integrated ORM, we think this is the course for you, and we hope to see you at cf.Objective()!

cf.Objective() Preconference Classes
28 January 2010 08:32 AM 15 Comments

ColdFusion 9 ORM and Transactions - It Does Not Mean What You Think it Means.

In one of my favourite lines from the Princess Bride -

[Vizzini has just cut the rope The Dread Pirate Roberts is climbing up]
Vizzini: HE DIDN'T FALL? INCONCEIVABLE.
Inigo Montoya: You keep using that word. I do not think it means what you think it means.


..and when using Transaction support with ColdFusion 9 ORM and Hibernate Sessions...It did not do what I thought it did. It did something else.

To give some back story: As we have discussed previously, a Hibernate Session is meant to flush at the end of a Hibernate marked Transaction.

So if we are talking to Hibernate natively (for example set up with JavaLoader), and had the following code:
mySession = sessionFactory.openSession();

foo = mySession.get("Foo", 1);
foo.setBar("fooBar");

trans = mySession.beginTransaction();

mySession.save(foo);

trans.commit();

mySession.close();
Which then translates to the following:
  1. Start a Hibernate Session
  2. Retrieve Entity 'Foo', with a key of 1, and assign it to a variable foo
  3. set the property 'Bar' on foo
  4. Start a Hibernate Transaction, which is tied to the Hibernate Session
  5. Tell the Hibernate Session to save() our Entity foo
  6. Commit our Hibernate Transaction, which will flush the Hibernate Session
  7. Close the Hibernate Session

If we attempt to do the same thing in ColdFusion, it may look something like this:

foo = EntityLoad("Foo", 1, true);
foo.setBar("fooBar");

transation {
    EntitySave(foo);
}

Which you would think would work exactly the same as above. Except or one small thing - It Doesn't.

If you read the ColdFusion Documentation on ORM Transactions, it states:

When <cftransaction> begins, any existing ORM session is flushed and closed, and a new ORM session is created. The <cftransaction> can be committed or rolled back using appropriate ColdFusion tags in <cftransaction>. When the transaction ends and has not been committed or rolled back explicitly, it is automatically committed and the ORM session is closed. If there is any error inside the transaction, without any exception handling, the transaction is rolled back.


This means that the above ColdFusion code, will actually perform like so:
  1. Start a Hibernate Session with the ColdFusion Request
  2. Retrieve Entity 'Foo', with a key of 1, and assign it to a variable foo
  3. set the property 'Bar' on foo
  4. Hit the start of the Transaction, flush the current Hibernate Session, close it, and then start another one.  At this point, foo has been persisted to the database, and is now detached (and remember detached is generally bad)
  5. Call EntitySave() on the now detached object foo
  6. Commit the Hibernate Transaction, and flush the Hibernate Session
  7. Flush the Hibernate Session, when the ColdFusion Request Ends

Or if you want to look at it another way, it would be the equivalent of doing the following native communication with Hibernate:
mySession = sessionFactory.openSession();

foo = mySession.get("Foo", 1);
foo.setBar("fooBar");

//foo actually gets persisted to the DB at this point
mySession.flush();
mySession.close();
mySession = sessionFactory.openSession();

trans = mySession.beginTransaction();

//foo is now detached
mySession.save(foo);

trans.commit();

mySession.flush();
mySession.close();

The big question at this point, is of course - Well, why does ColdFusion do it this way then?

There is actually a very good reason, although that reason (imho) is based on a few assumptions. 

The first assumption, is that you are going to write your ORM interactions inside your transaction block, like so:

transation {
    foo = EntityLoad("Foo", 1, true);
    foo.setBar("fooBar");

    EntitySave(foo);
}

The second  assumption is that, as a developer you will leave the ORM setting flushatrequestend set to its default of true, and therefore a split between the Hibernate Sessions is required.

For example, if we had the following code:

transation {
    foo = EntityLoad("Foo", 1, true);
    foo.setBar("fooBar");

    myMethodHereThrowsAnException();

    EntitySave(foo);
}

If we didn't have separate Hibernate Sessions, or at least clearing of the Session after Hibernate Transaction rollback, , the following would occur:
  1. Start a Hibernate Session with the ColdFusion Request
  2. Start the Hibernate Transaction
  3. Retrieve Entity 'Foo', with a key of 1, and assign it to a variable foo
  4. set the property 'Bar' on foo
  5. Throw an exception, which causes the Transaction to rollback
  6. The request ends, the Hibernate Session is flushed, and foo gets saved back to the database, since it is still available in the Hibernate Session.
Which is very much against the nature of a rolled-back transaction.

Instead, what actually happens is:
  1. Start a Hibernate Session with the ColdFusion Request
  2. Start the Hibernate Transaction, which closed the above Session, and starts a new one
  3. Retrieve Entity 'Foo', with a key of 1, and assign it to a variable foo
  4. set the property 'Bar' on foo
  5. Throw an exception, which causes the Transaction to rollback
  6. The Transaction end closes the current Hibernate Session, and creates a new one
  7. The request ends, the Hibernate Session is flushed, and nothing gets saved to the database, as there is nothing in the current Hibernate Session
Given the above assumptions, this is much better, since we want to have the Transaction actually rollback.

That all being said, what happens to those of us that want to work, or have an architecture that inclined towards our previous example:

foo = EntityLoad("Foo", 1, true);
foo.setBar("fooBar");

transation {
    EntitySave(foo);
}

I.e. We want to have our Transaction interact with the current Hibernate Transaction, and not flush at the end of the ColdFusion request, which, I find to be the solution I prefer for when building applications with Hibernate.

What can we do then?

There are two things that need to be done, if we want to do this kinda of approach. The first is, to set the ORM setting flushatrequestend to false.  This means that the Hibernate session won't flush at the end of the ColdFusion request, and we have complete control over when it does flush.

To make sure the Transaction interacts with the current request, we can't use <cftransaction> or a transaction {} block, we have to natively interact with the Hibernate Session directly, which is quite straight forward.

foo = EntityLoad("Foo", 1, true);
foo.setBar("fooBar");

trans = getORMSession().beginTransaction();

try
{
    EntitySave(foo);

    trans.commit();
}
catch(Any exc)
{
    trans.rollback();
    rethrow;
}

We have to do the extra work to manage the commit and/or rollback of the Transaction manually, but this something that could be implemented with a UDF or using Aspect Oriented Programming for reuse.

Now I can use Transactions to demarcate when I want the Hibernate Session to be flushed, and I'm not tied to wrapping my entire Entity operations inside a <cftransaction> block.

This is something I really like about how Adobe implemented the ORM integration.  If I don't particularly like the way an individual aspect has been implemented, I have direct access to the underlying engine, and can therefore interact with it in whatever way that suits the way I develop and thearchitecture of my application.

Now Transactions mean what I think they mean.
 
UPDATE 28/10/01:
I just wanted to add a small conclusion to this post, that sums what I am trying to get across simply.
 
Basically what this all boils down to is: If you are using <cftransaction> or a transaction{} block, make sure you are wrapping them around the entire operation, not just the EntitySave() portion at the end, as otherwise bad things can happen.

If you want to just wrap transactions around the EntitySave() part of your code, you will need to use native Hibernate Transactions like I have done above.
 
Hopefully that boils the large post above into a nice tasty nugget of knowledge that is far easier to swallow.

Presenting and Teaching at cf.Objective() 2010

I'm a little behind the times on this blog post - but I am presenting and also teaching a course at cf.Objective() this year.

I will be presenting 2 sessions at the conference:

Dependency Injection Redefined - ColdSpring 2.0: Narwhal

ColdSpring 2.0, codenamed 'Narwhal', is a project that has been going on a little 'behind the scenes', except for the occasional tweet from either myself, or Chris Scott.

In this presentation, we'll look at some of the motivations behind the complete rewrite of ColdSpring for the 2.0 version, and some of the new features that will be available that should make dependency injection easier, and way more flexible than ever before.

I've had in my to-do list a reminder to write a long blog post on what is going on with Narwhal, which I should write at some point soon, so you have a good idea what to look out for.  That being said, Narwhal is taking shape nicely, and I think is going to be a very powerful addition to the ColdFusion framework landscape.

Advanced Java & ColdFusion Integration with JavaLoader 1.0

This talk will focus on the new features of JavaLoader 1.0, and how you can use them to integrate Java with your ColdFusion platform in some new and exciting ways.  If you are interested in JavaLoader 1.0, check out this previous blog post, it gives you a good run down on the new features it brings to the table.

We will also be investigating some of more common 'gotchas' with Java and ColdFusion integration, especially around ClassLoader issues, which should be useful for all involved.


Bob Silverberg and I are also going to be a teaching a 2 day training course, just before cf.Objective():

Hands-On ColdFusion ORM Training

This will be as very hands on session, where Bob and I will be going through building an application using ColdFuson 9's Object Relational Mapper from beginning to end.  This will include many best practices, discussions as well as theory about how the underlying Hibernate engine works with ColdFusion.  No ORM/Hibernate experience necessary.

More detail on the course can be found on our website, and also on the preconference page, where you can also check out all the other fantastic training content.

Don't forget that the early bird pricing for both conference tickets, and training finishes on the 29th of January, which is coming up soon!

cf.Objective() is looking to be a great conference. Hope to see you there!

My Interview on Dzone - ColdFusion and Java Integration

The interview I did with Dzone at the Adobe MAX conference is now online!

In the interview we talk about a variety of topics, mainly centred about how and why to integrate ColdFusion and Java together, but also touching on things like Object Relational Mappers, including ColdFusion 9's integration with Hibernate.

Hope you like it, and please give it a nice 'up' on Dzone.

26 August 2009 02:46 PM 3 Comments

Getting UTF-8 and MySQL to work with ColdFusion 9 ORM

A question I've seen show up quite often in Hibernate forums is 'How do I get Hibernate to generate UTF-8 Compliant Tables and/or columns when it generates my database tables when using mySQL?'

It's actually, quite easy to do, but often (myself included), people end up looking deep into Hibernate for some mysterious setting.

In reality, it's just a question of setting up your database correctly.  The first thing you need to do is set your database to use UTF-8 character coding as its default, like so, when creating it:

create database my_new_database default CHARACTER SET = utf8 default COLLATE = utf8_general_ci;

This will ensure all tables that are created by ColdFusion's ORM are created with a UTF-8 character set.

That being said, I have seen issues when data is being sent up to MySQL in UTF-8 form getting corrupted.  To ensure the database drivers use the correct character set as well we add useUnicode=true&characterEncoding=UTF-8 to our MySQL connection string in the ColdFusion Admin under the datasource's Advanced Settings.

There you go! UTF-8 support in mySQL with ColdFusion ORM!

17 August 2009 07:03 PM 7 Comments

Overloading ORM Implicit Get and Set Methods

This is something I just ran into with ColdFusion 9's ORM implementation, that thankfully Rupesh got back to me very fast on, otherwise, I probably would have been confused for quite a while.

I needed to overwrite a get and set value in a CFC I was creating.  We will say for arguments sake I was hashing a password on a User object (even though I was doing something completely different), like so:

component output="false" persistent="true"
{
    property name="userid" fieldtype="id" ormtype="int" generator="identity" hint="primary key";
    property name="name" type="string" notnull="true" length="200" hint="The user's name";
    property name="password" type="string" length="200" hint="The user's password";

    public void function setPassword(String password)
    {
        instance.password = hash(arguments.password);
    }

    public String function getPassword()
    {
        return instance.password;
    }
}

This is how I would usually have written my Components, storing my data in variables.instance, so they wouldn't overlap with any of the data stored in my variables scope.

What I couldn't understand was, my password would keep getting stored in my database as NULL, even though I had explicitly set it.

Thankfully Rupesh explained that when the ColdFusion ORM retrieves and populates data in an ORM managed CFC, it directly accesses the variables scope in the CFC.  So in the above instance, the ORM was finding no data for the password, and interpreting that to mean that I wanted to insert that as NULL into my database.

Therefore,  to get my code to work was to store my data in the variables scope, like so:

component output="false" persistent="true"
{
    property name="userid" fieldtype="id" ormtype="int" generator="identity" hint="primary key";
    property name="name" type="string" notnull="true" length="200" hint="The user's name";
    property name="password" type="string" length="200" hint="The user's password";

    public void function setPassword(String password)
    {
        variables.password = hash(arguments.password);
    }

    public String function getPassword()
    {
        return variables.password;
    }
}

This way the ORM can find exactly what it is looking for, and I can manipulate my data the way I want.

The fact that the ORM integration works this way is actually a very good thing, as it means that my password above doesn't get hash'd over and over again, but it is something we all should be aware of when you want to overwrite the implicit get and set functions that get generated by <cfproperty> declarations.

04 August 2009 07:27 AM 12 Comments

ColdFusion 9 ORM - Explaining Hibernate Object State

In the previous two articles, we started the discussion of Hibernate Sessions and how they related to the ColdFusion 9 ORM.  We noted the fact that a Hibernate Session keeps track of what objects it loads, and can therefore update it when it realises that the object has changed.  The question then posses itself - if a Hibernate Session has closed, which happens at the end of every ColdFusion request, what happens to the objects that it was managing?

Going forward, I'm going to reuse the Musician model I used in the Introducing ORM in Adobe ColdFusion 9 beta Adobe DevNet article, for which the updated code samples can be found here.

The very short version for those who don't wish to look at the code, is a model in which we have a Musician, who has a name, and an age, and he/she also has a many-to-many relationship to an array of Instruments, which they can play.

As far as Hibernate is concerned, there are three different states for any Object that it interacts with.

Transient

An Object/Entity (you could use either word) is Transient, if it has just been created with a createObject() or new operator, but has yet to be saved with the EntitySave() method.

Obviously, if transient objects are not persisted via EntitySave(), then they never get stored in the database, and will eventually be garbage collected.

For example, our musician john below is a transient object:

 

<cfscript>
    import com.*;
   
    //this is transient
    john = new Musician("Transient John");
</cfscript>

Since john is never saved, it will always be transient.

Persistent

A Persistent object is one that has either come from, or has been saved in the database, within the scope of the current Hibernate Session (which is an important point to note).

For example, we can make our musician john below persistent, by:

<cfscript>
    import com.*;
   
    //join is transient
    john = new Musician("Transient John");
    
    john.setAge(47);

    //john is now persistent   
    EntitySave(john);
</cfscript>

Therefore, since john was inserted into the database, he is persistet.

By the same token, if we retrieve an object through the ORM, it is also persistent:

<cfscript>
    //larry's ID is 2

    //larry is also persistent
    larry = EntityLoad("Musician", 2, true);
    
    //As larry is persistent, we can change his age, which will be reflected in the database
    larry.setAge(19);
</cfscript>

Since larry was retrieved from the database, he is also persistent.

Detached

Detached objects are ones that used to be persistent, but the Hibernate Session has closed. Detached objects were one of the biggest things for me to wrap my head around when starting with Hibernate, and can cause a few really tricky errors to occur.

To explain detached a little better, we can go through a scenario that will causes them, as I think this is something that a lot of ColdFusion developers are going to end up running in to.

Let's have a new musician, called Tim, and time is going to have 2 instruments that he plays, the Flute and Piano.

We are going to grab Tim out of the database, and then put him in our ColdFusion Session scope, so we can keep track of him from request to request.

<cfscript>
    tim = EntityLoad("Musician", 2, true);
    
    session.musician = tim;    
</cfscript>

For this request, Tim will be persistent, however, on the next request, Tim is now detached, as the Hibernate Session will have closed at the end of the previous request.

Therefore, if I do this:

<cfscript>
    instruments = session.musician.getInstruments();    
</cfscript>

<cfdump var="#instruments#">

You will see the following (not well written) error:

failed to lazily initialize a collection of role: Musician.instruments, no session or session was closed

If you are running ColdFusion via the console, you will also see something similar to:

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: Musician.instruments, no session or session was closed


What does this error even mean? 

First of all, we should remember that the collection of Instruments our Musician can play are lazy loaded. This means they aren't actually loaded from the database into the object until you actually request them.

The important thing to note here, is that lazy loading with Hibernate can only occur if the Hibernate Session that the object was originally loaded from is still open.  To put it another way, if the Hibernate Session has closed, then Hibernate has no record of what the object was doing, and therefore can't do any lazy loading.

In the above example, since the previous ColdFusion request ended, the Hibernate Session has closed, and if you attempt to access a relationship that is set to lazy load, and has yet to be loaded, this error occurs.

Its should be noted that singular properties are not lazy loaded - therefore, if you are just grabbing a property on an object that is detached, no error will be thrown.

What can we do to mitigate this issue? There are a few options, one of which is, to simply retrieve the object all over again, like so:

<cfscript>
    session.musician = EntityLoad("Musician", session.musician.getMusicianID(), true);

    instruments = session.musician.getInstruments();    
</cfscript>

<cfdump var="#instruments#">
Or, like so:
<cfscript>
    session.musician = entityLoadByExample(session.musician, true);

    instruments = session.musician.getInstruments();    
</cfscript>

<cfdump var="#instruments#">

As then the object we are dealing with is considered persistent, as it is attached to the currently open Hibernate Session.  This tends to be the easiest of the options when dealing with detached objects.

Another interesting way of making our detached object persistent is like so:

<cfscript>
    EntitySave(session.musician);

    instruments = session.musician.getInstruments();    
</cfscript>

<cfdump var="#instruments#">

This may look strange, but what is actually happening when you call EntitySave(), is that it calls the Hibernate method saveOrUpdate()

A quick version of what saveOrUpdate() does is -

Therefore in the example above, the data stored in session.musician will be saved again to the database, and since session.musician is now deemed persistent, we can successfully do lazy loading of the instruments.

However, if a situation like this would occur:

<cfscript>
    musicianTwo = EntityLoad("Musician", session.musician.getMusicianID(), true);

    EntitySave(session.musician);
</cfscript>

We get the following error:

a different object with the same identifier value was already associated with the session: [Musician#2]

Since Hibernate deems the persistent object that is currently connected to the Hibernate Session much more important than the detached object, which makes sense, as the persistent object has the most up to date version of the data stored in the database.

Generally speaking, if you at all can, try and avoid having detached objects in your application, as this is generally a Good Thing™, and will allow you to avoid some pretty decent headaches as you develop with CF9 ORM.  Strategies such as storing IDs in the ColdFusion Session and having an API to return a new Object by that ID on request is often a good way to go, rather than storing the Entity itself in the ColdFusion Session.  That being said, if your architecture means that you have to have detached objects this series should be enough to give you a basic grounding the concepts of object state, and how to manage it.

If you want to learn more about managing Hibernate Object States (and there is far more to it than I have written here), you can read more about this in the Hibernate documentation, but this should hopefully have given you a decent enough overview to avoid some possible pitfalls when handling persistence with ColdFusion 9's ORM integration.
28 July 2009 08:41 AM 7 Comments

Updated Sample Code for Introduction to CF9 ORM DevNet Article

My apologies if this is a little belated, but here is an update to the sample code that was posted with my DevNet article Introducing ORM in Adobe ColdFusion 9 beta.

Unfortunately several things changed in CF9 between the time that I wrote the article and when the public beta came out.

The major differences between the sample on Adobe.com and this one are:

I will endeavour to keep this download up to date as new versions of ColdFusion 9 are release.

coldfusion9_orm_sample.zip

 

21 July 2009 08:32 AM 15 Comments

ColdFusion 9 ORM - More on Flushing Hibernate Sessions

Hopefully with my previous article, I've got you understanding how Hibernate Sessions work behind the scenes of ColdFusion.  However, there is one statement I made that requires further clarification before we go any further.

I wrote:
"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."

Technically this isn't exactly true, but it was a concept that confused me a lot when first starting with Hibernate, so I wanted to get people thinking in the right direction without complicating things too much.

The Problem

For example, a situation like this made me scratch my head for a long time when I first started working with Hibernate:

We have 5 Musicians in our database, and we want to delete one, and then re-list all of them again.

<cfdump var="#ormExecuteQuery('from Musician')#" label="query">

<p>We are now deleting!</p>
<cfset musician = entityLoad("Musician", 3, true)>
<cfset EntityDelete(musician)>

<cfdump var="#ormExecuteQuery('from Musician')#" label="query">

And we would see a result like:

Tom, Jerry, Ben, Bob, Richard

We are now deleting!

Tom, Jerry, Ben, Bob, Richard

This shows me exactly the same data we before and after my EntityDelete().  Wait... what? Didn't I delete Musician Number 3?

The fact of the matter is, yes, we deleted Musician #3, except since the Hibernate Session hasn't been flushed yet, the data hasn't been persisted to the database.  Therefore, when we run out HQL query, we see all the Musicians!

Hibernate Session Flushing

Before we go directly into how to solve this problem, what does the Hibernate documentation say about when Session Flushing actually occurs?

This process, called flush, occurs by default at the following points:
  1. before some query executions

  2. from org.hibernate.Transaction.commit()

  3. from Session.flush() 
So what does that actually mean in terms of ColdFusion?
  1. Before some query executions - So at some arbitrary points during the Hibernate Session life cycle it may flush.  Obviously not something we can rely upon.
  2. At the end of a Transaction. So if we our code in a <cftransaction> block, it should flush at the end of that transaction, and therefore the changes to our objects will be persisted in the database.
  3. When we call ORMFlush(), or at the end of a Session when it is called implicitly.

Therefore, if we wrap the relevant code in or Transaction, like so:

<cfdump var="#ormExecuteQuery('from Musician')#" label="query">

<cftransaction>
<p>We are now deleting!</p>
<cfset musician = entityLoad("Musician", 3, true)>
<cfset EntityDelete(musician)>

</cftransaction>
<!--- Session should be flushed now --->

<cfdump var="#ormExecuteQuery('from Musician')#" label="query">

We should get a result of:

Tom, Jerry, Ben, Bob, Richard

We are now deleting!

Tom, Jerry, Bob, Richard

Alternatively, we could also do:

<cfdump var="#ormExecuteQuery('from Musician')#" label="query">

<p>We are now deleting!</p>
<cfset musician = entityLoad("Musician", 3, true)>

<cfset ORMFlush()>
<!--- Session should be flushed now --->

<cfdump var="#ormExecuteQuery('from Musician')#" label="query">

And we would also see the same results.

So as you can see it is not exactly true that your object data will only get persisted at the end of you request, as you actually have a lot of control over exactly when the Session gets flushed.

It is important to note that 9/10 times you probably won't care when the Session gets flushed and the changes to your objects actually get persisted in the database.  However, there will be instances in which you will care, and your code depends upon having your data persisted in your database.  You now have the tools to manage your persistence life cycle and know what is going to happen when.

15 July 2009 11:26 AM 5 Comments

ColdFusion 9 ORM - Explaining Hibernate Sessions

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.

Hibernate Sessions

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 IMHO).

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
fred.age(32);

//close the session, which will update fred.
session.close();

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:
  1. opening a Session, i.e. we tell Hibernate 'Hi', which starts our conversation.
  2. Tell Hibernate to retrieve our Caveman fred, through our session.
  3. We change the age of fred to 32.
  4. 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 useful. 
To do this in Java, you could go:

session.flush();

But in ColdFusion you write:

ORMFlush();

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.

13 July 2009 03:12 PM 2 Comments

ColdFusion 9 Beta Drops, and so does my Devnet ORM Article!

As I'm sure you have all noticed, ColdFusion 9 Public Beta is now available for download.

I am really excited about this release, and think it is going to change the way a lot of people are going to be developing applications going forward.

Some of my favourite new features are:
So if you haven't already, grab a copy of ColdFusion 9 Beta, and ColdFusion Builder Beta, and enjoy!