Apr 25
Transfer ORM is, as the name implies, an object relational mapper for Coldfusion. Transfer has a myriad of advanced features which can be intimidating for newcomers. Fortunately, Transfer can be installed and used very easily without learning some of the more advanced features. What follows are instructions you can use to install, configure and use transfer in a few simple steps.
Installation
UPDATE: Transfer 1.0 is now available. The last official release of transfer is 0.6.3. This version is now quite old and it is recommended that you use the bleeding edge release (BER) from subversion. If you have any misgivings about using the BER, rest assured that many production systems are running the transfer BER. It's stable. To install the transfer BER, point your subversion client to http://svn.riaforge.org/transfer and checkout or export the source from /trunk/transfer. You can either set a mapping for "/transfer" in the cf administrator, or drop the source transfer folder in your web root.Configuration
To use transfer in an application you'll need to setup two configuration files. One for the datasource that transfer will use and another to describe the objects that transfer maps from your relational database. These files are typically named Datasource.xml and Transfer.xml, but you can use any name you like and/or append a .cfm extension to prevent the files from being visible in a web browser. Datasource.xml The transfer datasource.xml config specifies the values for the following: - a datasource name that currently exists in the cf administrator - a username (if required - leave blank otherwise) - a password (if required - leave blank otherwise)<?xml version="1.0" encoding="UTF-8"?>
<datasource xsi:noNamespaceSchemaLocation="../xsd/datasource.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<name>dsn_name</name>
<username></username>
<password></password>
</datasource>
Transfer.xml
The transfer.xml file is used to define the properties and relationships of transfer objects that are mapped to the relational tables in your database. Objects can have onetomany, manytoone, or manytomany relationships. The following xml is the object definitions from the tBlog sample app.
<?xml version="1.0" encoding="UTF-8"?>
<transfer xsi:noNamespaceSchemaLocation="../xsd/transfer.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<InvalidTagDefinitions>
<package name="user">
<!-- User details -->
<InvalidTag name="User" table="tbl_User">
<id name="IDUser" type="numeric"/>
<property name="Name" type="string" column="user_Name"/>
<property name="Email" type="string" column="user_Email"/>
</object>
</package>
<package name="system">
<!-- Different categories for Blog Posts -->
<InvalidTag name="Category" table="tbl_Category">
<id name="IDCategory" type="numeric"/>
<property name="Name" type="string" column="category_Name"/>
<property name="OrderIndex" type="numeric" column="category_OrderIndex"/>
</object>
</package>
<package name="post">
<!-- A Blog Post, with a Decorator of type com.Post -->
<InvalidTag name="Post" table="tbl_Post" decorator="tblog.com.Post">
<id name="IDPost" type="numeric"/>
<property name="Title" type="string" column="post_Title"/>
<property name="Body" type="string" column="post_Body"/>
<property name="DateTime" type="date" column="post_DateTime"/>
<!-- Link between a Post and the User it who wrote it -->
<manytoone name="User">
<link to="user.User" column="lnkIDUser"/>
</manytoone>
<!--
Link between a post and it's array of Comments
-->
<onetomany name="Comment">
<link to="post.Comment" column="lnkIDPost"/>
<collection type="array">
<order property="DateTime" order="asc"/>
</collection>
</onetomany>
<manytomany name="Category" table="lnk_PostCategory">
<link to="post.Post" column="lnkIDPost"/>
<link to="system.Category" column="lnkIDCategory"/>
<collection type="array">
<order property="OrderIndex" order="asc"/>
</collection>
</manytomany>
</object>
<!-- A comment for a blog post -->
<InvalidTag name="Comment" table="tbl_Comment">
<id name="IDComment" type="numeric"/>
<property name="Name" type="string" column="comment_Name"/>
<property name="Value" type="string" column="comment_Value"/>
<property name="DateTime" type="date" column="comment_DateTime"/>
</object>
</package>
</objectDefinitions>
</transfer>
Integration
Using Transfer with Coldspring<bean id="transferFactory" class="transfer.TransferFactory">
<constructor-arg name="datasourcePath"><value>/config/transfer/Datasource.xml</value></constructor-arg>
<constructor-arg name="configPath"><value>/config/transfer/Transfer.xml</value></constructor-arg>
<constructor-arg name="definitionPath"><value>/path/to/definitions</value></constructor-arg>
</bean>
<bean id="datasource" factory-bean="transferFactory" factory-method="getDatasource" />
<bean id="transfer" factory-bean="transferFactory" factory-method="getTransfer" />
Using transfer as an application scope "singleton".
<cfset transferConfig = StructNew() />
<cfset transferConfig["datasourcePath"] = "/config/transfer/Datasource.xml" />
<cfset transferConfig["configPath"] = "/config/transfer/Transfer.xml" />
<cfset transferConfig["definitionPath"] = "/path/to/definitions" />
<cfset application.transferFactory = CreateObject("component","transfer.TransferFactory").init(argumentCollection=transferConfig) />
<cfset application.transfer = application.transferFactory.getTransfer() />
Usage
To grasp the full breadth of the transfer API, you really need to review the Transfer docs. I'll cover the four methods you will likely work with the most in the beginning. They are, get(), new(), save() and delete(). Using the tBlog object definitions above, to retrieve a post object use:<cfset application.transfer.get("post.Post",1) />
To have transfer return a new instance:
<cfset post application.transfer.new("post.Post") />
To modify and save a new post:
<!--- create a new post --->
<cfset post = application.transfer.new("post.Post") />
<!--- retrieve category with id 1 --->
<cfset category = application.transfer.get("system.Category",1) />
<!--- set properties (not shown) --->
<!--- set category for post --->
<cfset post.setCategory(category) />
<!--- save the post --->
<cfset application.transfer.save(post) />
A small, but significant, benefit of using Transfer ORM, is that when you save an new object the object's state reflects it's new persisted state. So you can find out the new id by simply calling.
<cfset newid = post.getID() />
Lastly, transfer delete() method works like save(), you pass the transfer object to the method.
<cfset application.transfer.delete(post) />
Jun 10, 2008 at 2:16 PM A small quibble but the init() method of the transferFactory takes an argumentCollection containing the keys you placed into the transferConfig struct. Your example code, as written, will fail because you're passing in a struct and not appending argumentCollection= to the front.
Thanks for the article!
Eric
Jun 10, 2008 at 4:54 PM D'oh!
Thanks for catching that, Eric. I will update it immediately!
Jul 4, 2008 at 2:11 PM @paul - This is exactly the post I needed to see today. Just what I was looking for. Thank you!
Oct 13, 2008 at 10:23 AM Question:
What if you have a friggin huge datastructure in place already and the system is functioning using primarily Illudium generated CFCs. Creating this configuration file for my data structure would be hell!
Any ideas on if I could setup the datastructure / foreign key relationships in the database and then have it generate a Transfer.xml file based on this?
Please let me know your thoughts when you can!
Thank you!
Oct 20, 2008 at 2:35 PM Joshua,
Give this a try:
http://transferconfig.riaforge.org/
Cheers!
Sep 19, 2009 at 6:16 PM Perhaps you turned on ScriptProtect or something, but your transfer.xml code is full of InvalidTag blocks.
Jun 23, 2010 at 1:30 AM A military exercise, http://www.guccihandbagsoutlet.com/ gucci handbags outlet a shell from far away, and sent to check that the soldiers fell on farms, shells, TianZhongZheng http://www.guccihandbagsoutlet.com/ gucci outlet stand you, your tears brimming with dark clothes break ground say: stealing star cabbage with http://www.guccihandbagsoutlet.com/ gucci handbags shells are shot?
Aug 24, 2010 at 2:52 AM <p><a href="http://www.uggbootsretails.com" target="_blank">UGG Argyle Knit</a> features genuine twin-face sheepskin for refreshing comfort. It's one of our tallest boots and looks great all the way up or cuffed down. <a href="http://www.uggbootsretails.com" target="_blank">UGG boots</a> in our Classic Collection feature a soft foam insole covered with genuine sheepskin and have a molded EVA light such as <a href="http://www.uggbootsretails.com" target="_blank">UGG Sundance</a> and <a href="http://www.uggbootsretails.com" target="_blank">UGG Bailey Button</a>, the flexible outsole designed for amazing comfort with every step. Beat the chill in superior style with the <a href="http://www.uggbootsretails.com" target="_blank">UGG Ultra Tall</a>. The <a href="http://www.uggbootsretails.com" target="_blank">Bailey Button 1873</a> of light and flexible outsole along with a suede heel guard provides durable wear all season long. Detailed with three oversized wood buttons, this style can be styled up and buttoned, slouched and slightly unbuttoned, or completely cuffed. <a href="http://www.uggbootsretails.com" target="_blank">UGG Ultra Short</a> is also a good choice for people to refuge from the cold.Just buy one of the ugg boots for your family and yourself, it’s really a good gift both for you famlily and you.Action is better than thinking in heart.</p>