Photo from Chile

Managing Bi-directional Relationships in ColdFusion ORM - Array-based Collections

It's important to know that when you have a bi-directional relationship you should set the relationship on both sides when setting one side. There have been a number of discussions about this on the cf-orm-dev google group, including this one in which Barney Boisvert provides a very good explanation of why this is important. Brian Kotek has also written two articles on the subject in the past. If you're not already familiar with this topic I suggest you check out those links.

The general recommendation for addressing this requirement is to override the methods in your objects that set one side of the relationship (e.g., setX(), addX() and removeX()) so that they'll set both sides, rather than just the side of the object that was invoked. While doing some testing of the new CF9 ORM adapter for Model-Glue along with the new scaffolding mechanism that we're developing I needed to address this issue for a many-to-many bi-directional relationship. I found that there were a few wrinkles that made the task not quite as straightforward as I has originally imagined, so I figured I should share what I came up with.

[More]

Become a ColdFusion ORM Ninja in Just Two Days!

I've mentioned previously that Mark Mandel, the mastermind behind Transfer ORM, JavaLoader, ColdDoc, and now the lead developer of Coldspring, and I have developed an intensive, two-day, hands-on workshop on ColdFusion's new ORM features. We will be delivering that workshop, Developing Applications with ColdFusion 9 Object Relational Mapping, in Minneapolis, MN on April 20-21, 2010 which are the two days immediately preceding the cf.Objective() conference.

Really? I Can Master ColdFusion ORM in Two Days?

You bet you can! This is an extreme hands-on workshop. We won't be lecturing at you, we'll be working with you. For each concept that we cover we'll be writing code together, both the instructor and the students, working towards building a single, working application. Then, once we've done that together, you'll be let loose on your own to practice the concepts again on your very own project, which is yet another application which will be built incrementally using the concepts that you just learned. This means you'll have lots of chances to practice your newfound skills, and, more importantly, to make your own mistakes. You'll either figure out how to fix your mistakes yourself, with the help of one of your fellow students, or with the help one of the two instructors. You'll learn by doing, and what's more, you'll leave the class with lots of examples of working code that you wrote yourself.

This is why we say that we can help you master ColdFusion ORM in just two days. Not only will you be ready to start using it in your next project, but you'll also be in an ideal position to teach it to your fellow developers.

About the Instructors

I've been working with Transfer ORM for a few years, and have been working with ColdFusion's ORM integration since early in the product beta. I've blogged about it extensively, delivered a number of one-hour presentations on the subject and have created and regularly contribute to a Google group (cf-orm-dev) dedicated to discussing some of the more advanced and esoteric topics around ColdFusion's ORM integration.

As for Mark, in addition to creating his own ColdFusion-based ORM (Transfer), he's also worked extensively with Hibernate (the ORM that is integrated into ColdFusion 9) and is considered by many to be the foremost expert in all things ORM in the ColdFusion community. This therefore represents a unique opportunity to learn about this new, exciting and productivity enhancing technology from two people who know it very well, and have real-world experience developing with it.

Do I Have to Be an OO Guru to Attend?

Definitely not! We assume no prior knowledge of ORMs or Object Oriented programming, and the techniques that we teach can be used, if you wish, in a totally procedural application. So you neither need to know OO to join in, nor do you need to learn OO in order to use what you learn in your own work (although we would encourage you to do so). Some experience working with CFCs would be helpful, but we can get you up to speed pretty quickly even if you lack that.

Where is the Workshop Being Held?

As mentioned above, the workshop is running as a pre-conference training session at cf.Objective(), and will take place from April 20 - 21, 2010 at the conference hotel, which is the Hyatt Regency in Minneapolis, MN.

How Much Does it Cost?

We have made the early-bird price into a permanent discount, so although the original price was listed at $1200 for the two days you can now enroll for just $1000.

How Do I Sign Up?

You can register for the training via cf.Objective()'s registration form.

Can Anyone Attend?

Although the workshop is being offered as a cf.Objective() pre-Conference class, you don't have to attend cf.Objective() in order to enroll. So if you've having trouble getting your boss to pony up for a trip to cf.Objective(), perhaps you can convince him or her to at least send you to these two days of invaluable training.

What Topics Will Be Covered?

Here's a summary of the topics that we'll be covering:

  • Introduction to ORM
  • Introduction to Hibernate
  • Configuring ORM
  • Working with Objects
    • Creating an Object
    • Retrieving an Object / Lists of Objects
    • Updating an Object
    • Deleting an Object
    • Arrays of Objects vs. Queries
  • Mapping Objects
    • Ids and Properties
    • Many-to-One Relationships
    • One-to-Many Relationships
    • Many-to-Many Relationships
    • Formulas
    • Collection Mapping
    • Inheritance
    • Cascade Options
  • Hibernate Internals
    • Hibernate Sessions
    • Session Flushing
      • How It Works
      • How to Control It
    • Working with Transactions
    • Hibernate Object State
      • Transient, Persistent and Detached
      • How Objects Move between States
  • Lazy Loading
    • Overview
    • How it Affects SQL
    • Dealing with Detached Objects
  • Concurrency
  • HQL
    • What is HQL?
    • Basic Queries
    • Criteria / Parameters
    • Joins
    • Pagination
    • Bulk Updates
  • Application Architecture
    • Using a Service Layer with ORM
    • Using an Abstract Service
  • Caching
  • Event Handling
  • DDL (Database) Generation

Truly a Unique Opportunity

Although we do have plans to make the course available at other venues in the future, Mark and I live on opposite sides of the planet, and it just so happens that we'll both be attending cf.Objective() this year. It's likely that future classes will feature either Mark or I as instructors, as it's a rare occurrence that we're both in the same place at the same time, so don't miss this unique opportunity.

Looking for More Information?

I think I've covered most of what you need to know about the course in this post, but if you're looking for even more information about it please visit our web site at www.ColdFusionORMTraining.com.

ColdFusion ORM Gotcha - Non-String Struct Collection Keys

Here's another tricky issue when working with collections of child objects that are stored as structs. Just like last time, we'll look at a Department object with a one-to-many property that holds a collection of Users which is stored as a struct. The difference this time is that we'll use a numeric property as the key to the struct, rather than a string property:

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="SIN" ormtype="int";
5    property name="Users" fieldtype="one-to-many" type="struct"
6        cfc="User" fkcolumn="DeptId" singularname="User"
7        structkeycolumn="SIN" structkeytype="int" cascade="save-update";
8}

The nice thing about having the collection of Users in a struct is that we can access them individually. For example, if we have a Department object and we know we want the User in that Department with a SIN of 12345, we could simply write:

view plain print about
1Department = entityLoad("Department",1);
2User = Department.getUsers()[12345];

If you're like me you'd probably think that would work, but it doesn't.

[More]

Awesome Training Available Before cf.Objective()

As you're no doubt aware, cf.Objective(), "The World's Only Enterprise Engineering Conference for ColdFusion Developers", is coming to Minneapolis, MN from April 22-24, 2010. It's an outstanding opportunity to learn a ton of stuff, and to network and socialize with like-minded developers. I am pleased and honoured to be speaking, twice, for the second year in a row. What you may not realize, however, is that in the days prior to the conference there is a boatload of training available.

Developing Applications with ColdFusion 9 Object Relational Mapping

Mark Mandel and I will be delivering a comprehensive hands-on workshop on Developing Applications with ColdFusion 9 Object Relational Mapping for two whole days, from April 20-21, and it's going to be fantastic, if I do say so myself. If the new features of ColdFusion's ORM integration don't interest you (buy why wouldn't they?), there are five other choices.

Something For Everyone

Here's the full list of all of the courses available:

  • Building Secure CFML Applications (April 21) - Jason Dean and Pete Freitag
  • Coldbox:100 Training (April 21) - Luis Majano
  • Developing Applications with ColdFusion 9 Object Relational Mapping (ORM) (April 20-21) - Bob Silverberg and Mark Mandel
  • Getting Started with Flex and AIR Development with the Flex SDK (April 21) - John Mason
  • Mach-II and OOP from the Ground Up (April 20-21) - Kurt Weirsma, Peter Farrell and Matt Woodward
  • Rapid Development with Model-Glue 3 (April 20-21) - Dan Wilson and Ezra Parker

There really is something for everyone, and the instructors are all top-notch.

Anyone Can Attend

Something else you might not realize; you don't have to attend cf.Objective() in order to sign up for and attend a pre-Conference training class. So, if you've been hankering to learn more about CF9 ORM, application security, ColdBox, Model-Glue, Mach-II, or Flex and AIR development, go for it!

The Early-Bird Ends Friday

I'll close with a reminder; the discounted early-bird rates, which apply to both the cf.Objective() conference fee and to most of the pre-conference training sessions, expires this Friday, January 29th. So why not save some cash and sign up right now? Registration is done via the cf.Objective() registration form.

I hope to see many of you there in April.

More Fun with ColdFusion ORM Struct-Based Collections

Ben Nadel asked a question in a comment to my last post about struct-based collections with ColdFusion ORM which I thought was quite interesting and deserved some investigation. To recap the previous post, it simply pointed out that in order to add an object to a struct-based collection, when calling the add method one must pass both the object to be added to the collection and the key to be used in the struct. This raised a great question from Ben, whom I quote:

Does the ORM system do any validation on the Key that you pass in? Does it affect the way the data is persisted to the database (or will the persistence use the value as defined by the CFProperty structKeyColumn)?

I'd never tested this myself, so I did just that, and what I found was somewhat surprising.

[More]

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. ;-)

Filtering Collections in ColdFusion ORM

A question was asked on the cf-orm-dev Google Group about returning just a subset of objects that make up a collection. Specifically, the developer had a Page object and a Content object with a many-to-many relationship. A simplified version of the objects is:

Page.cfc:

view plain print about
1component persistent="true" {
2    property name="pageId" fieldtype="id" generator="native";
3    property name="title";
4    property name="contents" fieldtype="many-to-many" cfc="content"
5        singularname="content" linktable="page_content";
6}

Content.cfc:

view plain print about
1component persistent="true" {
2    property name="contentId" fieldtype="id" generator="native";
3    property name="column" ormtype="integer";
4    property name="pages" fieldtype="many-to-many" cfc="page"
5        singularname="page" linktable="page_content" inverse="true";
6}

Each Page can have multiple pieces of Content, and each Content block appears in a particular column on that page. Each Page can have multiple Content objects in any given column. The developer was wondering if he could do something like:

view plain print about
1Page = entityLoadByPK("Page",1);
2column1Contents = Page.getContents({column=1});

Which would return all of the Content objects assigned to that Page, but only those that are in column 1 (which is a property of the Content object).

[More]

Previous Entries / More Entries