Aliaspooryorik
ColdFusion ORM Book

CF9 ORM - Clearing the session cache

Ben Nadel recently wrote an interesting post entitled Learning ColdFusion 9: When Does An ORM-Enabled Object Get Persisted. What Ben demonstrates is that when an Entity that has previously been saved is updated in a completely different request, the chnages that you make are automatically saved to the database when then request ends regardless of whether you called EntitySave or not. That last bit is important!

This all sounds well and good, but it does cause an issue if you design your applications so that validation occurs within the Entity. Essentially, this approach is where you can populate your object with all kinds of random data and then call a validation method which returns a result indicating if the entity is valid or not. Depending on the result, you either go ahead and save the data or return an bunch of validation error messages.

With the way that the hibernate sessions are handled in ColdFusion 9 (bearing in mind that it is still in Public Beta), you can't do this as when your request ends, ColdFusion will tell hibernate to commit any changes, including your invalid data. Not good.

Thankfully, there is a new function called ORMClearSession, which according to the docs: "ORMClearSession removes all the entities that are loaded or created in the session. This clears the first level cache and removes the objects that are not yet saved to the database."

What it doesn't make clear is that when it clears the cache, it doesn't commit any unsaved enties first. Here is some simple code to demonstrate.

User.cfc


/**
* I am a User Entity
*/

component persistent="true" table="tbl_User" output="false"
{
/*
Set up the persisted properties
The first line refers to metadata for ColdFusion
The second line refers to metadata required to create the database columns
*/


/**
* I am the unique identifier, which is numeric and generated for you
*/

property name="IDUser" fieldtype="id" generator="native" type="numeric" default="0"
ormtype="integer" notnull="true";
/**
* I am the Name of the User which maps to the user_Name column in the database
*/

property name="Name" type="string"
ormtype="string" column="user_name" length="50" notnull="true";
/**
* I am the Email Address of the User which maps to the user_Email column in the database
*/

property name="IsNew" type="boolean"
ormtype="string" column="user_new" length="20" notnull="true";


public any function init( name, isnew ) output="false"
{
if ( StructKeyExists( arguments, "name") )
{
this.setName( arguments.name );
}
if ( StructKeyExists( arguments, "isnew") )
{
this.setIsNew( arguments.isnew );
}
return this;
}

}

create.cfm


<cfset new User( "aliaspooryorik", true ) />
<cfset EntitySave( User ) />
<cfdump var="#User#" />

debug.cfm


<cfset User = EntityLoad( "User", {name="aliaspooryorik"}, true ) />
<cfdump var="#User#" />

update.cfm


<cfset User = EntityLoad( "User", {name="aliaspooryorik"}, true ) />
<cfset User.setNew( false ) />
<cfdump var="#User#" />

<cfif !StructKeyExists( url, "persist" )>
<!--- discard changes without saving them --->
<cfset ORMClearSession() />
</cfif>

9 comments

  1. John, very cool. So, I suppose that once you have called ormClearSession(), you have to manually save the object with EntitySave() if you want to persist it?

    Comment by Ben Nadel – August 03, 2009
  2. Hi Ben, yes you can call EntitySave( User ) after ormClearSession() and it will then persist the changed entity to the database.

    Thanks for the original post - got the brain cells firing :)

    Comment by John Whish – August 03, 2009
  3. John, thanks, this is going to save me a few hours of thinking.

    Super thanks.

    Comment by John Allen – August 03, 2009
  4. @John,

    No problem - it's been many of your ORM posts that got my brain firing ;)

    Comment by Ben Nadel – August 03, 2009
  5. It's probably worth also pointing out that if you do something like this:

    EntitySave( User );
    // populate new object and validate here....
    // validation fails so don't commit
    ORMClearSession();

    The changed entity will not be saved. If you need to the EntitySave to commit to the database then you'll need force an ORMFlush like this:

    EntitySave( User );
    ORMFlush();
    // populate new object and validate here....
    // validation fails so don't commit
    ORMClearSession();

    Comment by John Whish – August 03, 2009
  6. Ahhh, yeah, good point. That would have caused some serious headache!

    Comment by Ben Nadel – August 03, 2009
  7. I don't know how happy I am with clearing the Session entirely - you can never be quite sure what is going to be cleared and what is not going to be cleared.

    There are definitely some other options -
    Duplicate() the CFCs you want to populate, validate them, and then merge() them back into the current session.

    You could also change the flushMode of the current session to only commit on Transaction commit, which would also solve a lot of problems.

    Or if you really want to - just evict() the object that has been populated (although you may also have to evict it's children as well, unless you set them up with cascade=evict... I can't remember if you can do that in cfproperty).

    I see too many people getting caught out using the clear all approach, as when they want SOME data to be stored, and some data to be ignored, they will get into trouble.

    Comment by Mark Mandel – August 03, 2009
  8. @Mark,

    Ahh, that sounds good. I haven't gotten that far in the documentation yet.

    Comment by Ben Nadel – August 04, 2009
  9. Hi Mark, I knew that if anyone would have a better solution then it would be you!

    As I understand it using Duplicate() would create a deep copy of the entity along with any objects that the entity references, which sounds like it might create as many problems as it solves.

    My initial thought was to wrap the code in a transaction and I've got some code that does this, but that would be a real pain when porting an existing application.

    Just from reading your comments, I like the idea of evicting the entity, but handling the children is going to be a pain as well.

    Hmmm, great comments Mark - lots to think about :)

    Comment by John Whish – August 04, 2009

Leave a comment

If you found this post useful, interesting or just plain wrong, let me know - I like feedback :)

Please note: If you haven't commented before, then your comments will be moderated before they are displayed.

Please subscribe me to any further comments
 

Search

Wish List

Found something helpful & want to say ’thanks‘? Then visit my Amazon Wish List :)

Categories

Recent Posts