Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at CFUNITED 2008 (Washington, D.C.) with:

Learning ColdFusion 9: Refreshing And Rebuilding An ORM Application

By Ben Nadel on
Tags: ColdFusion

Disclaimer: I am learning about ColdFusion 9's new ORM features as I go - I am not an authority on this topic by any means.

When you use the ORM features in ColdFusion 9, ColdFusion has to create a number of Hibernate configuration files and component mappings. These configurations are created when the application starts up (either running for the first time, having timed out, or being stopped manually with ApplicationStop()). From what I can gather, there are two aspects to this configuration process:

  1. Configuring the database.
  2. Configuring the ColdFusion component mappings.

The first part, configuring the database, depends on the dbCreate ORM settings defined in the Application.cfc:

  • <!--- Do not alter the database. --->
  • <cfset this.ormSettings.dbCreate = "none" />

This ORM settings property, dbCreate, can take one of three values:

  • None: The default, tells the ORM system not to alter the database in anyway.
  • Update: Tells the ORM system to create any tables that do not exist or to update any existing tables with new columns or properties.
  • DropCreate: Tells the ORM system to drop existing tables and recreate them.

The second part of the configuration process, setting up the ColdFusion component mappings, will happen when the application starts up, or when you call the ColdFusion 9 method, ORMReload(). ORMReload() can be called at any time to update the ORM mappings, but be careful because you might end up mapping a CFC property to a database column that does not yet exist:

 
 
 
 
 
 
 
 
 
 

As you saw in the video, when we added a property to the Task.cfc ColdFusion component and then called ORMReload(), ColdFusion remapped all the properties in the ORM system. The problem with this is that the newly mapped property does not yet have a corresponding column in the database; and so, when we go to save our newly mapped object, we get the ColdFusion error:

'ISCOMPLETE' is not a column in table or VTI 'APP.TASK'.

The ORM system is trying to persist the IsComplete property of the Task.cfc instance; but since ORMReload() didn't update the database, this action fails.

As it turns out, however, this last statement - that ORMReload() didn't update the database - is not entirely true. ORMReload() doesn't update the database most of the time because the ORM Setting, dbCreate, in the Application.cfc is set to or defaults to "none." When you call ORMReload(), it actually updates the ColdFusion component mappings AND carries out the ORM Setting's dbCreate command. Therefore, if we change the dbCreate property to "update" or "dropcreate", ORMReload() will, in fact, update the database structure.

 
 
 
 
 
 
 
 
 
 

(Note: I sound a bit confused in the video because I actually recorded that one first. At the point of writing this, my understanding of the re-mapping process was stronger than it was 30 minutes ago.) As you can see in the video, by using Refresh and Rebuild URL flags, I both update the ORM settings and call ORMReload(). This will update the ColdFusion component mappings and alter the database as necessary.

Application.cfc

  • <cfcomponent
  • output="false"
  • hint="I define the application settings and event handlers.">
  •  
  • <!--- Define the application. --->
  • <cfset this.name = hash( getCurrentTemplatePath() ) />
  • <cfset this.applicationTimeout = createTimeSpan( 0, 0, 5, 0 ) />
  •  
  • <!---
  • Store the datasource for this entire application. This
  • will be used with all the CFQuery tags as well as by
  • the ORM system.
  • --->
  • <cfset this.datasource = "cf9orm" />
  •  
  • <!---
  • This will turn on ORM capabilities for this application.
  • This tells ColdFusion to load all of the Hibernate code
  • and to communicate with the datasource above to prepare
  • the configuration files.
  • --->
  • <cfset this.ormEnabled = true />
  •  
  • <!---
  • This will define how the ORM system will work. Because
  • we are not starting out with any database, but using the
  • ORM system to build the database, we want to turn off
  • the use of the DB to get mapping data - we will be
  • defining all of the mapping information in our CFCs.
  •  
  • NOTE: "None" is the default for dbCreate. I have left it
  • in here only because I am overriding it afterwards.
  • --->
  • <cfset this.ormSettings = {
  • dbCreate = "none",
  • useDBForMapping = false
  • } />
  •  
  • <!---
  • Check to see if we need to rebuild the database. Normally,
  • these ORM settings only take effect when the application
  • is starting up; however, if we change them here AND then
  • call ORMReload() later on in the page, these settings seem
  • to take effect without stopping the appliation first. The
  • call to ORMReload(), however CANNOT be inside the
  • Application.cfc pseudo constructor.
  • --->
  • <cfif !isNull( url.rebuild )>
  •  
  • <!---
  • Signal to the ORM that we want to drop and then re-
  • create our database.
  • --->
  • <cfset this.ormSettings.dbCreate = "dropcreate" />
  •  
  • </cfif>
  •  
  • <!---
  • Check to see if we need to update the database (adding
  • columns and mappings that might not have previously
  • existed. Like the other ORM Settings, this only takes
  • effect when the application is restarted... OR, if
  • ORMReload() is called on the same page.
  • --->
  • <cfif !isNull( url.refresh )>
  •  
  • <!---
  • Signal to the ORM that we want to update existing
  • tables or add new ones.
  • --->
  • <cfset this.ormSettings.dbCreate = "update" />
  •  
  • </cfif>
  •  
  •  
  • <cffunction
  • name="onRequestStart"
  • access="public"
  • returntype="boolean"
  • output="false"
  • hint="I intialize the request.">
  •  
  • <!--- Define the request settings. --->
  • <cfsetting showdebugoutput="false" />
  •  
  • <!---
  • Check to see if the refresh of rebuild flag is
  • present. If it is, then we need to reload the ORM
  • mappings and configuration.
  • --->
  • <cfif (
  • !isNull( url.rebuild ) ||
  • !isNull( url.refresh )
  • )>
  •  
  • <!--- Reload the ORM configuration and mappings. --->
  • <cfset ORMReload() />
  •  
  • </cfif>
  •  
  • <!--- Return true so that the page can run. --->
  • <cfreturn true />
  • </cffunction>
  •  
  • </cfcomponent>

By default, ColdFusion will rebuild all of the ColdFusion component ORM mappings when the application starts up. If you want to rebuild these mappings at any point, you can either restart the application by calling ApplicationStop() (and then making a subsequent page request to start the application), or you can call ORMReload(). ORMReload() will update the ORM mappings and execute the dbCreate command in the ORM settings defined in the Application.cfc.




Reader Comments

I am on the fence as to whether or not I'm keen on the Hibernate integration that has been done. It's nice, but I do worry that it may become the ORM solution for CF, instead of just one of many options. And options are good. (My reticence may also stem from my preference for Transfer, I admit.)

A whole pile of stuff just got injected into the core language -- I guess it's just going to take me a while to get used to it.

Reply to this Comment

@Rick,

My concern right now is that I feel it's distracted me from the fact that I don't fully understand how to use objects. For example, just because we have ORM it doesn't mean that my issues with data validation are any different. But now, I'm so distracted by learning a completely new methodology of SQL abstraction that I won't even worry for the moment that the validation throws errors.

It's like taking two steps to the side, later to realize, you still need to take a step forward at some point.

Reply to this Comment

These posts about how to fire it ColdFusion ORM up will be valuable for many people. Took a little getting used to with "update" and "dropCreate". My Application.cfc looks a lot like yours.

I've been a Transfer fan boy and have been using it on numerous project for a while.

It took a little bit of getting used to but this release of CF is the Bees Knees. The Hibernate integration is da-bomb and I am very pleased with the implementation.

Only thing I wish adobe would add would be a "clearXXX()" method like Transfer has to remove all objects from a collection.

Reply to this Comment

@John,

I'm glad you're really liking this release - that gives me hope that Hibernate will start to click a bit more in my head.

As far as the clearXXXX(). You should be able to call: setXXXX( [] ).

Reply to this Comment

search the google then find your site.
that is a really excellent post.

Thanks for the post.

Reply to this Comment

One note, Update will populate new columns if they don't exist, but it won't change settings on those properties (columns). I altered a length parameter on one of my columns and this change did not persist to the DB.

If you change this.ormSettings.dbCreate = "dropCreate" it will change the table to reflect this change.

Reply to this Comment

Great Blog, thank you.

I got this working - sorta -
I have an empty mySQL db and I use your ?rebuild
on a simple index.cfm the cf server takes about 4 to 5 seconds and then returns an error msg to the page that myDB.myTable doesn't exist and then gives link to the docs.

However, I check the db and the table was actually created. Next, I run the same index.cfm with ?refresh and no error msg.

I've deleted the tables and tried it a few times and on some occasions it returns the same error msg that myDB.myTable doesn't exist - but this time the server says the application.cfc has and error on the line with <cfset ORMRefresh() />

Any suggestions? (rebooting no help)

Reply to this Comment

@Drew,

You are saying that it won't change the properties of an existing column?

@TomLong74,

Hmm, are you making any references to the ORM entities before you run the ORMReload() method? That's the only thing I can think of, especially if subsequent page requests don't cause any errors.

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.