Photo from Chile

CF9 ORM Gotcha - Adding Items to a Struct Collection

I was just bitten by this one, so I thought I'd quickly blog it to help anyone else who comes across it. If you've got a one-to-many or a many-to-many property in your ColdFusion ORM entity, and you've specified that the collection of objects should be stored as a struct, when adding an item to that struct you must pass both the key for the item and the item itself into the add method. For example, using the following Department object:

view plain print about
1component persistent="true" output="false" entityname="Department" {
2    property name="DeptId" fieldtype="id" generator="native";
3    property name="Name";
4    property name="Users" fieldtype="one-to-many" type="struct"
5        cfc="User" fkcolumn="DeptId" singularname="User"
6        structkeycolumn="UserName" structkeytype="string" cascade="save-update";
7}

Forgetting that I had to specify the key for the struct as well as the object, my first take at adding a User object to the Department's collection of Users was something like this:

view plain print about
1Department = entityLoad("Department",1);
2User = new User();
3User.setUserName("Bob");
4Department.addUser(User);
5entitySave(Department);

Unfortunately, this code throws an error stating "The User parameter to the ADDUSER function is required but was not passed in." Being a bit dim-witted, I was totally confused by this. "Hey," I said to my computer, "I know that I'm passing a User object into the method." It took me awhile to remember that I had to pass both key to the struct and the User object into the addUser() method. Changing the code to:

view plain print about
1Department = entityLoad("Department",1);
2User = new User();
3User.setUserName("Bob");
4Department.addUser("Bob",User);
5entitySave(Department);

Did the trick. So remember:

  • When adding an item to a collection that is a struct, you must pass both the key to the struct and the object into the add method.
  • You must pass the key to the struct in as the first argument, and the object as the second argument.

Conversely, when removing an item from a struct collection using the remove method, you only need specify the key to the struct. I hope this tidbit saves someone else the time that ColdFusion stole from me. ;-)

How I Use Transfer Today - A Gateway MapFactoryBean

I left something critical out of my last post about how I'm using Transfer (an ORM for ColdFusion) these days.

If you've been following along you'll know that I'm using an Abstract Transfer Decorator, which all of my concrete decorators extend, and that I'm using Brian Kotek's most excellent Bean Injector to load singletons into my Transfer objects. This raises an interesting issue: How to inject the appropriate Gateway Object into my Transfer Object.

[More]

My Take on Transfer ORM Event Model - BeforeCreate Example

Paul Marcotte wrote a blog entry describing how to automatically set a CreatedDate and ModifiedDate in your Transfer Objects when they are saved to the database. It is very well written and provides a great description of the problem, how Transfer observers work, and a solution.

I have used Transfer observers in a different manner, so I added a comment with a brief description to the blog entry. Dan Wilson suggested that it was too bad that such useful information was buried in a blog comment, so I decided to post it here as well. For the background, please check out Paul's entry.

[More]

Dynamic Datasources with Transfer and Coldspring

I have different datasource names on my local machine, in my dev environment and in my production environment, and I wanted to figure out a way to automagically tell transfer which datasource to use based on the server it's running on. I couldn't find any programmatic way of doing this with Transfer, as it seems to require a datasource.xml file. I decided to blog my solution, as it may be useful to others, or perhaps someone will point out a much better way to do it.

Here's what I'm doing:

I create 3 separate xml files, datasource_localhost.xml, datasource_dev.xml and datasource_prod.xml. Each one contains the name of the appropriate datasource.

In my Coldspring.xml file, where I define the Transfer bean, I use this code:

[More]