
Introduction to ORM in ColdFusion
Traditionally in ColdFusion we have used<cfquery/>
to hold SQL code that interacts with our data for inserting, updating, and returning one or more records back from our data stores. At best, most developers find this process to be redundant for simple functions. We will be looking at a new paradigm where our code that interacts with databases is easier to write, easier to update, and in some cases, more featured.
A side benefit to using ORM that most have not considered is that it makes code more portable. If you want to share code you write or code that others write in your applications, one of the historical obstacles would be making sure they were using the same SQL platform as you. ColdFusion 9 has put a superb interface on a technology created for the Java world called Hibernate. In the same style that working with<cfquery/>
has kept data interaction simple, this interface is somewhat like data technology 2.0 for ColdFusion developers. We still have the simple power but also have second generation features that will take us far into the future. So if you take an application built with Oracle via ColdFusion ORM, you can use the same basic application on a server running MySQL, MSSQL, or even Derby. Of course you will also be able to customize it for specific SQL platforms to run special features if desired.
ORM-enabled application configuration
The first thing we need to do is create an Application.cfc
file with the minimal requirements of configuration. We must include two settings for the ORM to work. We must include the ormenabled
and the datasource
variables in our Application.cfc
file. We will also use one of the default databases (cfartgallery
) that came installed with the ColdFusion server:
<cfcomponent> <cfscript> this.name = "CF9DT_ch4"; this.ormenabled = TRUE; this.datasource = "cfartgallery"; </cfscript> </cfcomponent>
Note
Application.cfc
is never meant to be run on its own, so do not expect this code to run by calling it direcly.
We can see that things are simple so far. We will continue to focus on what it takes to replace the basic functionality we have been using in the previous versions of ColdFusion. Yet, we need to remember that none of that functionality has been removed. The ORM technology is only an alternative way to manage data for those who want to use newer, fancier features.
Next we need to create a CFC which uses a technique called a "mapping". There is a table in the database called art
. We will use that table for our first example. We will have three files when we test the code:
Application.cfc
- (ORM) CFC for the table(s) we interact with
- Page (a
.cfm
file) where the CFC will be used
ORM-enabled CFCs
Let's now look at creating our ORM CFC. The first thing we need is to set up our CFC so it knows it is an ORM-based data object. We need to set some attributes for our main component tag. The first is the persistent attribute. This tells ColdFusion and Hibernate to persist this object mapping. The next is the table attribute where we declare the table that our object will be representing. This may be hard to believe but if we want to ignore relations and other details, we could use this ORM object with no additional changes. Save the following code to a file called ART.cfc
for our first object. If you want you can use the one in the Chapter 4 directory of the sample code:
<cfcomponent persistent="true" table="ART"> </cfcomponent>
Now we can create our page to use the ORM object. Our first objective is to create an object based on the ART.cfc
ORM file. We will see that these are referred to as "entity" objects. We will simply call this object ART
because ColdFusion 9 knows how to find the database entity object that matches. One of the amazing aspects of this new technology is all the things that happen without writing code to make them happen. This example will show how we can connect to the database through the entity and return the current number of rows. Now this is seen as an array of structures from the perspective of how ColdFusion sees the entity data. We will loop over the data and output each item to the browser screen. We use the data entity (each item) as an array object and pass the array item followed by a getter, returning an item value, using the field name. So to get the table field artName
, we use getArtName()
and it returns the value for that row in the database:
<cfset data = entityLoad("art")> <cfoutput> <cfloop from="1" to="#arrayLen(data)#" index="iRow"> Art : #data[iRow].getArtName()#<br/> </cfloop> </cfoutput>
We cannot make it easier to work with data than this. We will do some things that are not that easy as the chapter progresses, but first let's run this page and see what we get:

Now that is easy enough for about anyone to pull and place data on the page. Let's take a look at what the code would look like if we put in the description for each field of data. Before we do that let's also add one line of code, just for testing, in our Application.cfc
file. The ormsettings
is a structure that can do many powerful things for us. We should not leave this line on a live server, but this is good for testing because it makes sure our data ORM object is loaded fresh on each server request.
<cfcomponent> <cfscript> this.name = "CF9DT_ch4"; this.ormenabled = TRUE; this.datasource = "cfartgallery"; this.ormsettings = {autorebuild="true"}; </cfscript> </cfcomponent>
Note
Application.cfc
is never meant to be run on its own, so do not expect this code to run by calling it directly.
Now here is the code we would have if we provided a more detailed description about each field in our ART
table:
<cfcomponent persistent="true" table="ART"> <cfproperty name="ARTID" ormtype="int" fieldtype="id" /> <cfproperty name="ARTISTID" ormtype="int" /> <cfproperty name="ARTNAME" ormtype="string" /> <cfproperty name="DESCRIPTION" ormtype="clob" /> <cfproperty name="PRICE" ormtype="double" /> <cfproperty name="LARGEIMAGE" ormtype="string" /> <cfproperty name="MEDIAID" ormtype="int" /> <cfproperty name="ISSOLD" ormtype="short" /> </cfcomponent>
We have a name that can be but does not have to be the same as the actual field name in the database table. The column name must match the name of the data table field unless you want to add the column attribute with the correct name of that field. We actually do not need to list the ormtype
attribute, but we did it here to show the universal data types used by the Hibernate ORM interface. One very important thing to note is that our primary key should be set with a fieldtype
attribute having an ID value. We could also set a generator type containing any of the following values: increment, identity, sequence, sequence-identity, seqhilo, uuid, guid, native, assigned, select, foreign
. Until we gain more experience, it is good to use the default of assigned.
Understanding entities
When we used queries we would refer to the results of the query by the query name and the field name separated by a dot. So it would be art.artname
to retrieve the value for a row. Now if we are using an individual item with ORM, we would use art.getartname()
to accomplish the same results. With a query we could not change the values and save them back. This is one of the differences between ORM and query-based data interaction. Now we can use the same results to update the records in the database. We will look at that in just a moment, but first let's look at pulling a single record back from the database rather than an array/collection of records:
<cfscript> art = entityLoad("art"); piece = entityLoadByPK("art",4); </cfscript> <cfoutput> Art : <br> (piece) = #piece.getArtName()#<br> (art[4]) = #art[4].getArtName()#<br> </cfoutput>
Here we are pulling a particular item using the primary key for the piece
entity. The art
is a collection of entities stored in an array. We can see in the output segment of our code that we pull the same results. This tells us we can approach this in multiple ways and it is equally functional. Here is the output when sent to a browser:

What if we want to change the value of a record stored in the database? How do we modify the value using ORM entities? We use setters which are work coded in the same manner as our getters. If an entity already exists, then we are modifying the existing record. We will modify our previous example to show that we will not only be able to change the value of a record stored in the database, but also be able to modify the value using ORM entities at the same time. ColdFusion with the ORM technology sees that both of these are methods talking about the same entity object. We will add the following lines to our code:
<cfscript> art = entityLoad("art"); piece = entityLoadByPK("art",4); </cfscript> <cfoutput> Art : <br> (piece) = #piece.getArtName()#<br> (art[4]) = #art[4].getArtName()#<br> <hr> <cfset piece.setArtName("PAULO_updated")> (piece) = #piece.getArtName()#<br> (art[4]) = #art[4].getArtName()#<br> </cfoutput>
We can see that the entity piece
has been modified with the setArtName()
method. Yet both the piece and the fourth item in the array are updated because they refer to the same entity or record in the database. ColdFusion manages this for us under the hood and keeps things simple. Caution: Be sure you have the correct variable identified when modifying variables. We just happen to have the same array position for item four as we do for the record's primary key in the database. So be careful not to take the wrong concept from the code. Typically the array position of the entity returned in a collection will not match the primary key ID. We just got lucky. Luck is not a good way to code:
