Entries Tagged as 'Transfer ORM'

Some random post CFUnited thoughts

CFML , ColdFusion , Transfer ORM No Comments »
Now that CFUnited's over (at least for me) and I've had some time to rest and mull over things, I wanted to post a few random thoughts and opinions:
  • The entire L'Enfant Plaza Metro station (columns, walls, even some of the Metro railcars that passed through) was one big ad for Adobe LifeCycle. The message: LifeCycle can help the government manage and distribute PDF forms. Unusual? I don't get down into DC too often, but I'd never seen any one company take over an entire station like that before. I want to see more of this high-visibility marketing from Adobe, especially for ColdFusion.

  • Sean Corfield's new asynchronous event-driven framework, Edmund, looks very cool. Being able to fire off events and have them bubble up through the framework much like what you can do in Flex is a very appealing idea.

  • Twitter once again proved to be a useful tool. I found it a lot easy to "tweet" what was going on instead of writing it up on the blog, and thanks to Nafisa Sabu and Elliot Sprehn of TeraTech, anyone who visited the CFUnited website could read the tweets of the conference-goers who had "friended" the CFUnited Twitter account. Hopefully a few folks found my tweets to be useful.

  • While the proposed integration of Hibernate in ColdFusion 9 sounds neat, I think Transfer is still going to be the ORM of choice for many developers, both now and in the future, for some of the reasons Mark listed in his blog and because Transfer works/will work on a larger number of CFML platforms (CF7, CF8, and probably OpenBD and Railo).

  • The discussion about whether or not ColdFusion and ColdFusion development is becoming too Java-like isn't over yet. I met a developer who made the point that it seemed strange (and stupid) to him that we're trying to entice Java developers to use CFML because it makes development faster and easier while we seem to be gravitating towards adding complexity to our development process and our code.

    I made the usual argument that regardless of the focus on OOP in the ColdFusion blogging community, no one was advocating removing those aspects of ColdFusion that make CFML easy to learn and use, and that even OO-style programmers will admit that there are some situations where using an OO application framework is overkill, but he wasn't entirely convinced.

    It made me wonder: if Adobe does develop a teaching curriculum as part of their effort to get ColdFusion adopted in schools, will that curriculum take advantage of CFML's traditional low learning curve, or will they emphasize an OO-style of programming from the get-go?

  • Some promising ideas came out of Brian Meloche's session on promoting ColdFusion/CFML outside of the community. The existence/promise of OpenBD and Railo and Adobe's decision to make ColdFusion free for educational use has opened up a whole new world of possibilities. You should be hearing about these ideas soon, either via the CFConversations podcast or some other channel.

  • Which reminds me, you should check out the CFConversations podcast if you haven't done so already. And I would say that even if I wasn't involved with the project. :)

Using a Transfer decorator to get related records within the same table

ColdFusion , Transfer ORM No Comments »

 

One of the benefits of using the Transfer ORM in your application is that if you define the relationships between your tables in the Transfer XML configuration file, you can retrieve any objects related to your current object through a variety of functions.

However, sometimes you need to relate records within the same table. For example, in my current project, I have a table of item records which need to be arranged in a hierarchy of unknown depth: one set of items could have two levels of hierarchy, another three levels. Each item, therefore, can have one parent item above it (identified by a parentId field in the record) in the hierarchy and any number of children below it (and all the child records have the current item's ID as their parentId value).

How can you use Transfer to access these in-table relationships? One way is by using a decorator object. As the Transfer documentation explains, a decorator is a CFC file you write yourself that extends the TransferDecorator CFC that comes with Transfer. You associate your decorator with the Transfer object that represents the table in your Transfer configuration file so that when a Transfer object for a record in that table is generated, the functions you define in your decorator become part of that object. So say I define a Transfer object called "Item" in the package "example". Here is the XML in the Transfer configuration file:

 
<package name="example">
 <object name="Item" table="itemsTable" sequence="itemId_seq" decorator="com.itemDecorator">
    <id name="itemId" type="numeric" />
    <property name="setId" type="numeric" column="setId" />
    <property name="itemTitle" type="string" column="itemTitle" />
    <property name="itemText" type="string" column="itemText" />
    <property name="itemOrder" type="numeric" column="itemOrder" />
    <property name="parentId" type="numeric" column="parentId" />
  </object>
  
</package>

The decorator to be called is the itemDecorator.cfc in the "com" directory. I want to have two new functions in the decorator, one that returns a Transfer object for the parent record, and one that returns an array of Transfer objects representing each child record. Here's the code:

  
<cfcomponent displayname="itemsDecorator" extends="transfer.com.TransferDecorator" output="false">
  <cffunction name="getMyParentItem" access="public" output="false" returntype="any">
    <cfreturn getTransfer().get("example.Item",getTransferObject().getParentId()) />
  </cffunction>

  <cffunction name="getMyChildItems" access="public" output="false" returntype="array">
    <cfset var local= StructNew() />
    <cfset local.childrenArray= ArrayNew(1) />
    
    <cfset local.childrenQry= getTransfer().listByProperty("example.Item","parentId",getTransferObject().getItemId(),"itemOrder")>
    <cfoutput query="local.childrenQry">
       
       <cfset ArrayAppend(local.childrenArray,getTransfer().get("example.Item",local.childrenQry.itemId))>
    </cfoutput>
   <cfreturn local.childrenArray />
  </cffunction>
</cfcomponent>

In a decorator CFC that extends the TransferDecorator CFC, you can access the current item's Transfer object all of its functions via the getTransferObject() function, and you can access the main Transfer object via the getTransfer() function. So the single statement in the getMyParentItem() function in the decorator CFC is equivalent to:

 
<cfset parentItemObject= transfer.get("example.Item",currentItemObject.getParentId())>

The getMyChildItems() function is slightly more complicated because it needs to retrieve a recordset of child objects first, using the listByProperty() function of the main Transfer object (again, provided via the getTransfer() function within the decorator), then loop through those records, creating a Transfer object for each child record and appending it the array returned by the function.

What if the item record in question is either at the top of the item hierarchy or at the bottom? If there is no parent item, the Transfer object returned by the getMyParentItem() function will have an itemId of 0 (the default value for an empty numeric primary key) and empty values for all of the other properties, so you can test for that condition. If there are no child items, the array returned by the getMyChildItems() function will simply be empty.

This is only the second Transfer decorator I've ever written, so there may be a better way of going about it, but it gets the job done with just two short functions added on to existing object functions provided by Transfer. I like it when things are this easy.

 

A tip regarding many-to-many relationships in Transfer

ColdFusion , Transfer ORM No Comments »

Thought I should share this so no one else ends up learning it the hard way like I did yesterday.

In Transfer, you use an XML configuration file to describe your database tables and the relationships between them. You can define three types of relationships: one-to-many, many-to-one, and many-to-many.

The many-to-many relationship is used when one table is related to another table through the use of a linking table. In the introductory Transfer example files I looked at today, the many-to-many example is an application with an Events table, a Categories table, and an Events-Categories table containing a foreign key field referring back to the Events table primary key field, and a foreign key field referring back to the Categories table primary key field.

Now, when you define a one-to-many or many-to-one relationship between two tables, you describe both tables in the Transfer configuration files: they each have their own <object> XML block so Transfer objects can be created based on them. What I did not realize until today, when I looked more closely at those example Transfer files, is that you DO NOT create an <object> XML block for the linking table. The many-to-many relationship that you describe within one of other two tables' <object> block tells Transfer all it needs to know to relate the two tables.

Now, if I had read the Transfer documentation more carefully, or if I had tested my Transfer configuration file either against the included schema file or with testing code as I made changes to it, I probably would have figured this out a lot faster. But because I didn't do either of those things, I was baffled by the inscrutable and inconsistent error messages returned by my application when I started working on the CRUD operations involving those tables.

So in addition to the tip itself, my other piece of advice is to take your time and carefully read (and think about) the documentation when you start working with a new framework like Transfer: it may be easy to get started with, but you might miss a subtle detail or two that can get you in trouble.