Blog posts made on 07-Jul-09
Presenting At Adobe Developer Tech Day In Shanghai

I'll be in China all next week to meet with local Adobe personnel, customers, and partners, in Beijing and Shanghai. And I'll also get the opportunity to present an opening session at an Adobe Developer Tech Day on July 16th, in Shanghai.

Read More ›

ColdFusion E-Seminar: Ultimate ColdFusion

Join Mike Kelp from EdomGroup Inc. as he discusses how he leverages ColdFusion 8 to build highly scalable, high performing web applications for top organizations in the professional sports arena. The session, Ultimate ColdFusion: High performance, scalability and features, is tomorrow, Wednesday, July, 8, 2009 at 11:00 A.M. West Coast time.

Read More ›

ORM - Rethinking ColdFusion Database Integration

Database integration is a hallmark of ColdFusion applications. Indeed, the <cfquery> tag was one of the first added to the language, and to this day remains ones of the most used. There is an inherent simplicity and flexibility to being able to create database queries on the fly, so as to be able to refer to column names to work with results. There's also a real downside to this type of database integration. After all, consider what would happen to your code if a table name changed, or if columns were refactored and split, or if whole schemas were updated. Scary, huh? The downside of how most of us integrate databases into our ColdFusion apps is that we tend to write database specific code even at the client level, the code generating output or working with form fields, for example. In addition, we inevitably must write DBMS specific SQL, and that DBMS specific code needs to be managed by our applications.

Before I go any further, I must point out that <cfquery> is not going away, and it remains a very simple and powerful database integration option. For many of us, and for many apps, <cfquery> is, and remains, highly appropriate. But, having said that, in ColdFusion Centaur we're adding support for a newer way to think about database integration, leveraging Object Relational Mapping (ORM). ColdFusion's ORM support is built on Hibernate, the premier ORM implementation in Java development, and in fact, Hibernate is built right into the next version of ColdFusion, and exposed via ColdFusion Components and language elements.

ColdFusion's ORM support requires extensive coverage, which is way beyond the scope of this post, but here are the basics. In ORM, you never write SQL statements, and never really consider tables of rows and columns, at least not when writing client code. Instead, developers using ORM work with objects. For example, a table containing books with columns named title and author and ISBN, would have a corresponding object with the same properties. When using ORM, instead of retrieving a row from a table, you'd retrieve a book object (which is automatically populated by the contents of the table row). To retrieve all rows you'd not use a SELECT * FROM Books, instead you'd use Entity functions to request an array of book objects, populated and ready to use. And then instead of referring to column names in your code, you'd use Get methods in the returned objects. This is actually far less confusing than it sounds, so let's look at an example. First the Application.cfc:

view plain print about
2    <cfset this.ormenabled=true>
3    <cfset this.datasource="cfbookclub">
this.datasource is used to define the datasource to be used, and then this.ormenabled is set to TRUE to turn on ORM support.

Next we'll need an object that represents the table to be used, and in ColdFusion objects are implemented as ColdFusion Components (if you are working with multiple tables you'd have multiple CFCs, one for each table). Here's Books.cfc which maps to the Books table in the specified datasource:

view plain print about
1<cfcomponent persistent="true">
2    <cfproperty name="BOOKID" column="BOOKID" datatype="integer" length="10" />
3    <cfproperty name="AUTHORID" column="AUTHORID" datatype="integer" length="10" />
4    <cfproperty name="TITLE" column="TITLE" datatype="string" length="255" />
5    <cfproperty name="BOOKDESCRIPTION" column="BOOKDESCRIPTION" datatype="clob" length="2147483647" />
6    <cfproperty name="BOOKIMAGE" column="BOOKIMAGE" datatype="string" length="50" />
7    <cfproperty name="THUMBNAILIMAGE" column="THUMBNAILIMAGE" datatype="string" length="50" />
8    <cfproperty name="ISSPOTLIGHT" column="ISSPOTLIGHT" datatype="character" length="1" />
9    <cfproperty name="GENRE" column="GENRE" datatype="string" length="50" />

Notice that there are no methods (functions) in this CFC, there are only <cfproperty> tags that correspond to the table columns. And actually, the <cfproperty> tags are optional, and if omitted ColdFusion will read the database table to implicitly define the properties for you! Also, note that the CFC is named Books.cfc, so it maps to the Books table. If the table name changed, or if you needed to use a different CFC name, you could use the optional <cfcomponent> table attribute to specify the table name to use.

Oh, and it's worth noting that the new ColdFusion IDE (the subject of a future post) comes with wizards to generate these table CFCs for you.

And finally, here's how to retrieve the Books data. First we'll retrieve all books (this is equivalent to a SELECT *, but instead of returning a query, an array of Books objects is returned):

view plain print about
1<!--- Get data --->
2<cfset data=EntityLoad("Books")>
3<!--- Display titles --->
5<cfloop array="#data#" index="book">
6    #book.GetTitle()#<br>

Of course, sorting and filtering and more are all supported. For example, to retrieve books with an author id of 10 (equivalent to a SQL WHERE clause) you could use the following:

view plain print about
1<!--- Get data --->
2<cfset data=EntityLoad("Books", {authorid=10})>

Notice that to access the Title property, a GetTitle() method is used. This is a getter, and it is automatically created by ColdFusion. There are also setters, used to set properties within an object. To save a new or updated object you'd simple do the following:

view plain print about
1<cfset EntitySave(data)>

This would work for an insert or an update, just save the object and ColdFusion and Hibernate figure out whether to update an existing row or insert a new one.

And we've even made it easier to bridge between using ORM and working with queries (for example, to be able to use <cfoutput query="">, and more), just use the EntityToQuery() function to convert basic arrays of entity objects to familiar ColdFusion queries.

There's a lot more to ORM and ColdFusion's Hibernate integration. And ColdFusion developers get access to all of Hibernate, be it support for relational tables, lazy loading, caching, query optimization (by tweaking HQL directly), controlling all ORM settings, and much more, too. The next ColdFusion gives you the power of Hibernate with the productivity that is uniquely ColdFusion.

Read More ›