ColdFusion ORM - Attaching calculated values to your entities

Word Count: 308

There will come a time when you need to add a calculated value to your entity. In this example we will look at why you would want to do this and how you can easily accomplish it. I whipped up a very simple user manager example. First we have some orm settings in our application component. The main thing to get out of this is that we are going to be using event handling.

Our user entity is very basic and there is nothing special going on at this point. Now what if we wanted to display the users age somewhere in our code? We could easily do something like this. What if we had more of a complex calculation though? This is not logic that you would want to have to add everywhere this value is needed. Luckily we can easily add a field to our entity without persisting it to the database. The first thing we do is add the property and set persistent to false. This tells our entity that when we save/update we are not storing this property.

At this point your thinking that we could probably just write a setter that would calculate the age right? Short answer yes, long answer is no. If we take a closer look you will see why. If you were to use the user entity below and load a record the age property will be null. Your next thought would be to add it to the constructor right? Well, turns out this would not work either because your trying to set the age when we don't have date of birth loaded yet. That is where event handling comes in. I have talked about event handling before so I am not going to get into how it works. Just know for this example if event handling is turned on we have many methods available for us to listen for. One of them is post load and it happens after an object has been loaded. This is a perfect time to calculate age because we have our date value now. Finally there is one more check we need to run. What if the date of birth is null? If it is we are going to get an error when we try and calculate our age. We can run a quick check to make sure its not null.

Comments

#1 Posted By: Bob Silverberg Posted On: 1/18/10 1:11 PM
Interesting idea, but I'd probably accomplish the same thing a different way. I'd simply create a method called getAge() which encapsulates the logic. If you need to have a property exist to match that method (e.g., if you have code that looks for properties and generates UI elements), then simply add the non-persistent property exactly as you have done, and then the getAge() method would override the implicit getAge() method that CF creates for you.

I personally don't see any value in persisting the result of setAge() in a property, and with the current example it would even cause a problem. What if I do:

User = entityLoadByPK("User",1);
User.setDob('2010-01-18');
theAge = User.getAge();

theAge will contain the age of the User when the record was loaded, not the current age based on the dob that I just set. This could be fixed by overriding the setDob() method to call setAge() after setting variables.dob, but why?

What advantage is there to having an actual value in the age property, versus always calculating it on the fly with a getAge() method?
#2 Posted By: Dan Vega Posted On: 1/18/10 1:18 PM |
Author Comment
Well my hopes were if it was a property then it would act like just another field from the database. I wanted to turn that array of entities into a query and access that field just like any other column. I quickly found out this would not work though because when I call entityToQuery() it does not include that property.

If it is a property though I maybe able to roll my own, but as you said the question now becomes is it really worth it.

Thanks for the comments here and on the list Bob!
#3 Posted By: Barney Boisvert Posted On: 1/18/10 2:02 PM
I'm with Bob, a getter is a much cleaner way to implement the functionality. If the computation is expensive (so you don't want to do it every time), then you can use an internal cache, but it should still be a getter.

Hibernate provides a way to map an object property to a SQL formula, so if you can realize your computed value that way, you'd still get your ORM/Hibernate goodness. Not sure if CF9 supports that or not, however. For a lot of stuff, SQL is sufficient to do your computation, though you do have to be careful of changes to your mappings, since you're not querying your object model, you're querying the database (which is unfortunate, but at the same time understandable).


Post Your Comment

Leave this field empty







Show Captcha

If you subscribe, any new posts to this thread will be sent to your email address.

Copyright © 2007 Dan Vega | BlogCFC was created by Raymond Camden. This blog is running version 5.8.001.