Aliaspooryorik
ColdFusion ORM Book

CF9 ORM - Clearing the session cache II

Yesterday I posted, CF9 ORM - Clearing the session cache. The genius that is Mark Mandel, pointed out that while my approach solves the problem, it was a bit of overkill. So, this lead me to have a closer look at the methods available to a hibernate session.

You can access the hibernate session using the new to ColdFusion 9, ORMGetSession() method. I'm only going to use a few of the available methods which are; evict(), isDirty() and getFlushMode().

Hibernate can run in several modes, which dictate when the cache is flushed. By default, ColdFusion uses AUTO, but it is worth noting that you can set your preferred mode. For example if your application is read-only, then the MANUAL mode is the most effiicent. Alternatively, the COMMIT mode only flushes the cache when a transaction is committed. Setting the right mode for your application could reset in much better performance.

I'm sticking with the AUTO mode for the code below as that is the default.

OK, back to the problem. ColdFusion will commit any changes to an Entity that is persisted end of a request, regardless at the of whether you have called EntitySave or not. If you architect your applications so that Entites are responsible for validating themselves then this is a problem.

In my last post I used the ORMClearSession method to clear the cache of any unsaved entites. Whilst this works, it will remove all unsaved entities across the whole application. A much better solution is to just clear the specific entity from the cache. To do this we can use the evict method of the hibernate session.

Here's some sample code (using the Persisted CFCs from the ORMBlog sample app)


<cfoutput>

<p>What Session Flush Mode are using?<br />
#ORMGetSession().getFlushMode()#</p>

<!--- get an existing entity --->
<cfset Post = EntityLoadByPK( "Post", 1 ) />

<p>Any Changes to entities in the hibernate session?<br />
#ORMGetSession().isDirty()#</p>

<p>Let's update our Entity...</p>

<cfset Post.setTitle( "Posted " & Now() ) />

<p>Any changes to entities in the hibernate session?<br />
#ORMGetSession().isDirty()#</p>

<p>Let's evict our changed entity from the cache...</p>

<cfset ORMGetSession().evict( Post ) />

<p>Any Changes to entities in the hibernate session?<br />
#ORMGetSession().isDirty()#</p>

</cfoutput>

So what about relationships?


<cfoutput>

<!--- get an existing entity --->
<cfset Post = EntityLoadByPK( "Post", 1 ) />

<cfset Category = EntityLoadByPK( "Category", 1 ) />
<cfset Post.addCategories( Category ) />

<cfset EntitySave( Post ) />
<!---
Note as we are evicting this entity later
this EntitySave does nothing unless we
call ORMFlush() before the evict()
--->


<p>Categories Count<br />
#ArrayLen( Post.getCategories() )#</p>

<p>Any Changes to entities in the hibernate session?<br />
#ORMGetSession().isDirty()#</p>

<p>Evict the post from the hibernate session...</p>

<cfset ORMGetSession().evict( Post ) />

<p>Any Changes to entities in the hibernate session?<br />
#ORMGetSession().isDirty()#</p>

</cfoutput>

I should mention that some more testing is required to see how this works with entities that inherit or have more complex relationships, but it's a good start!

 


5 comments

  1. @John,
    One thing that you will have to keep in mind is that evict for Post here might not evict Categories from the session - depending on the cascade value.

    Comment by Rupesh Kumar – August 04, 2009
  2. Talking to Bob Silverburg, I just realised something -

    There is an ORM Setting already available to us in CF9: flushatrequestend.

    By default this is true, but it sounds like for situations like this, it makes more sense to turn it off, and therefore the session should only be flushed on transaction end, OR you explicitly call ORMFlush().

    That should make things easier!

    I've not tried this out, but it seems viable.

    Comment by Mark Mandel – August 05, 2009
  3. @Rupesh, good point and one that Mark had mentioned in the comments of my last post as a potential issue. It's definitely something I need to look at in more detail. I'd be interested to know how the engineering team would handle this issue.

    @Mark, I'm still getting my head around hibernate sessions, but calling ORMFlush() flushes all CRUD operations across the whole application so as I understand it, another request may be validating an object, which will be committed when a separate request calls ORMFlush() which is going to cause issues. Transaction commit would not have this issue but all CRUD operations would need to be wrapped in a transaction. Am I making any sense?

    Comment by John Whish – August 05, 2009
  4. John,
    ORMFlush will only flush the currently active session. It can never affect any other request or any other session. So be assured that ORMFlush will not mess-up the state of your application.

    Comment by Rupesh Kumar – August 05, 2009
  5. @Rupesh, Ah right so the hibernate session is associated to the request. That makes life easier!

    Incidentally I've voted for Mark's ER for allowing evict for property

    cfbugs.adobe.com/cfbugreport/flexbugui/cfbugtracker/main.html#bugId=79276

    Comment by John Whish – August 05, 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