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:

  • Turns off the Hibernate session being flushed at the end of the request
  • Stops the Hibernate session being flushed at the beginning of a transaction
  • Stops the Hibernate session being cleared when a transaction is rolled back

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.

Leave a Comment

Comments

  • Henry | October 12, 2011

    "Stops the Hibernate session being flushed at the beginning of a transaction" and "stops the Hibernate session being cleared when a transaction is rolled back"… can you explain them in more details? So what shall one do to manage the hibernate session now? Just plain old cftransaction? Thanks

  • Mark | October 12, 2011

    For details on how Transactions are managed with ORM, you can read:
    http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WS11EF87BF-AA62-40ce-BA11-602F6A4D9164.html
    http://help.adobe.com/en_US/ColdFusion/9.0/Developing/WSbfbbf049491c37b01e63e3d129fe08c786-8000.html

    And I also wrote this article a ways back as well, going into more detail:
    http://www.compoundtheory.com/?action=displayPost&ID=464 (this was before the 9.01 fix though).

    Re: "So what shall one do to manage the hibernate session now? Just plain old cftransaction?" – exactly. It becomes far simpler at this stage. Transaction demarcate where the Session gets flushed, nothing else, which makes things far simpler to manage.

  • John | October 19, 2011

    This is very helpful, thank you.

    If, as you say, transactions demarcate where the session gets flushed, what happens with nested transactions? I know the cf docs say that if transactions are nested "only the outermost cftransaction tag takes effect." Does this hold true for the flushing of Hibernate sessions? That is, is the session flushed only when the outermost transaction is complete?

  • Mark | October 19, 2011

    @John, that is a very good question!

    I believe that is the case, yes, but I’ve not tried it. I will have to give it a go and get back to you (or give it a shot if you get to it first, and let me know the result).

  • John Allen | November 22, 2011

    Can you give an example of how/what/and why you are using annotations in your HBMXML files? Sounds neat.

  • Christian Kostenzer | February 16, 2012

    Hi,
    thanks a lot for that interesting post.
    Where do you set the isDevEnvironment var ?
    Thanks

  • Mark | February 17, 2012

    @Christian
    This was just a made up function. I assume you would write it yourself that would do your own determination of what environment you are in.

  • Sean Walsh | May 12, 2012

    Hi Mark,

    You mention that you use HBMXML files for your mappings – is it possible (or even desirable) to map all of your entities in a single file, or do I need a separate file for each entity?

    I realize this is kind of an old post, but hopefully you’re still monitoring the comments on it. 🙂

    Thanks!

    Sean

  • Henry Ho | May 12, 2012

    AFAIK each cfc needs an HBMXML. However it’s not that bad ’cause once you turn "savemapping" on, all the *.cfc will have their HBMXML. Then customize the ones you needed, and deleted the ones you don’t need. 🙂