ORM PersistenceService BER

Okay so as of today, the bleading-edge release of DataFaucet includes a reasonably complete INITIAL PROTOTYPE of the PersistenceService. It now includes reciprocal one-to-many/many-to-one relationships and the purge operation has been given some preliminary testing. Aggregation (many-to-many relationships) have not been tested and cache purging needs some additional testing.

What does this mean?

For those of you who are advanced users and may have been interested in an "external ORM" where you could use your own business objects that are ignorant of the persistence engine, you can now have components like this:

<cfcomponent displayname="conference">
<cfproperty name="conferenceid" type="uuid" required="true" key="1" />
<cfproperty name="conferencename" type="string" required="true" />
<cfproperty name="forumArray" type="array" required="false" />

...
</cfcomponent>

<cfcomponent displayname="forum">
<cfproperty name="forumid" type="uuid" required="true" key="1" />
<cfproperty name="forumname" type="string" required="true" />
<cfproperty name="conference" type="conference" required="true" />

...
</cfcomponent>

Now where I put those elipses, you would have your getters and setters (however you want to write them) and in the PersistenceService you can set a pattern for them, so you can use either getValue/setValue the way I mostly use DataFaucet or you can use getConference/setConference. And then you can simply request your objects from the service in much the same way that Transfer works. In this above example when you request a conference object via PersistenceService.get("conference",conferenceid) it will automatically load that conference object with an array of its cached forums and similarly, each forum object will be loaded with a reference to the cached conference object. So if you've got one conference and 5 forums, you'll have 6 objects in the cache.

Can't wait?

For more information about how to configure the service, see the previous blog entry. There is NOT any documentation in the distribution yet. To get the code, export from the SVN repository (it's NOT in the public download yet and won't be until there's documentation).

In my mind there are specific use cases in which this is beneficial over using the existing active records and imo vice versa as well.

On the plus side:

Using the PersistenceService means that your individual cached objects won't contain all the data access methods as is the case with active record objects. That means they'll have a smaller memory footprint.

For some of you OO enthusiasts you'll be happy that the object is nearly independent of the ORM (aside from a few special attributes in the cfproperty tags).

Also there's just one DAO class, instead of having a separate DAO CFC for each object, woohoo! The DAO is loaded with some information about the class it's being used to persist, but generally speaking you shouldn't need to extend the DAO, it should just work as is to persist most business classes.

On the minus side:

Because of the seamless, recursive nature of the links between these objects, it could be really easy to code yourself into a situation where you've got dozens or even hundreds of objects loading when you only asked for ONE. As an example, given a product catalog of any size, you wouldn't want to have an array of Products in each Category obect. And that's really not the way online shopping is done anyway, so hopefully that won't be a problem for you. ;)

As of right now there are no solutions to lazy-loading property arrays. I have a few ideas about ways to handle that, but no code yet. Doing that in ColdFusion will probably mean subclassing your business objects to add hooks into the ORM for fetching those properties, although there will need to be a way of informing the DAO that those properties will be lazy-loaded.

Race conditions... race conditions... and more race conditions... To be honest there are race conditions with the active record implementation also, however, the addition of caching for any collection of objects increases the number and type of race conditions that will occur in your application. Unfortunately beyond "in your business objects", I can't tell you where you'll find them, I just know that you will. If any given method in your business objects sets or gets more than one instance variable, there's a potential race condition in it.

Use Cases

You might want to use the PersistenceService instead of active records if you have a behavior-rich application in which a number of objects need to remain resident in memory for frequent access. A good example of this would be application security / authentication. User objects, Role objects and Permission objects (if you have them) are apt to be accessed rather frequently and may include somewhat rich behaviors for determining which users have access to what features of your application. In this scenario it makes a lot of sense to retain these objects in memory to reduce the amount of database access and keep the individual objects readily accessible to each other to handle their exchange of information.

As always, I'm available to answer whatever questions you may have. ;)

Comments
BlogCFC was created by Raymond Camden. This blog is running version 5.5.006. | Protected by Akismet | Blog with WordPress