Thursday, October 22, 2009

ColdFusion 9 ORM Custom Naming Strategy

I'm pretty particular when it comes to naming conventions. If I'm working with code and objects, I prefer properties to be in written in camel case. However, I like database fields to be written in proper case, with all spaces replaced with underscores. For example, I would have user.id and user.firstName in my code, but User.ID and User.First_Name in my database.

Hibernate is able to automatically generate your database schema for you based on your *.hbmxml files, which can be automatically generated for you by ColdFusion after creating your Entity CFCs. While this can be a really handy feature for development, I was a little annoyed when Hibernate generated all of my columns in camel case to match my properties.

Then I found a really nice post by an Adobe engineer that talked about using a custom naming strategy, which is a component that Hibernate can use to generate your database table and column names.

In your Application.cfc, you can set this.ormSettings.namingStrategy to a CFC that implements the "cfide.orm.INamingStrategy" interface.

cfide.orm.INamingStrategy

component {

public string function getTableName(string tableName) {
}

public string function getColumnName(string columnName) {
}

}


With that in mind, here's my UncamelizeStrategy.cfc

component implements="cfide.orm.INamingStrategy" {

public string function getTableName(string tableName) {
return uncamelize(tableName);
}

public string function getColumnName(string columnName) {
return uncamelize(columnName);
}

private string function uncamelize(string name) {

var array = [];

for (var i=1;i <= len(name);i++) {
var char = mid(name,i,1);

if(i == 1) {
arrayAppend(array,ucase(char));
}
else {
if(reFind("[A-Z]",char)) {
arrayAppend(array,"_" & char);
}
else {
arrayAppend(array,lcase(char));
}
}
}

var newName = arrayToList(array,"");

if(newName == "Id") {
newName = "ID";
}
else if(right(newName,3) == "_Id") {
newName = left(newName,len(newName)-3) & "_ID";
}

return newName;

}

}


I'm sure there's probably an easier way to write this, perhaps using a regular expression, but I chose the brute-force approach of looping over each character. Short and simple.

1 comment:

  1. Cool stuff. I didn't even know about the naming strategy stuff.

    ReplyDelete