Hibernate and Inheritance
I'm already used to the magic that is Transfer and I can't imagine building a ColdFusion application without it. Adobe have said they're looking at integrating Hibernate into "Centaur" and showed some simple examples of how it might work in their keynote at CFUNITED (I expect we'll see more at MAX - you are going to MAX, right?). Hibernate is the de facto standard ORM for the Java world and it is very robust, scalable and feature-rich.
We've been using Hibernate for a while to manage the persistence of our business objects and that has driven us toward Groovy for those business objects since, right now, you cannot use Hibernate with ColdFusion Components in any meaningful way and we didn't want to write all the verbose code that Java would require.
A recent discussion on the Transfer mailing list has focused on how to model one-to-one relationships and why Transfer doesn't support them directly. This is one area in which Hibernate's features go far beyond what Transfer offers - and part of the reason for us to "switch" to Hibernate for future product development.
Another modeling quandary when it comes to persistence is how to handle inheritance.
Suppose you have a number of "content" object types such as blog entries, bookmarks, files and tasks. They all extend a base content type so that common behavior can be applied polymorphically across all types of content, such as adding comments or rating an item. You have several choices on how to represent this in a database: one table for each child object (with the parent object's data represented as columns in each child object's table), one table for the base class data and one table for each child object (with a one-to-one relationship between child and parent - hence the paragraph above), a single sparse table for all data types (with a discriminator column indicating what type of data that row holds and columns being null where they do not apply), or other options involving association tables and so on. The nice thing about Hibernate is that it handles all of these options out-of-the-box.
In our example, most of the metadata about content is held in the base class and the child classes only have a few additional fields. We're using Hibernate annotations so we can declare our base content class like this:
@Entity
@Table(name="content")
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(
name="content_type",
discriminatorType=DiscriminatorType.STRING
)
class Content implements Serializable {
- How we want Hibernate to represent the inheritance in the database - as a single sparse table
- How we want Hibernate to distinguish between different types of object in the table - it will add a column called content_type of type varchar (or whatever your database uses for string data)
@Id @GeneratedValue
Long id
@Entity
@DiscriminatorValue("bookmark")
class Bookmark extends Content {
String link
}
@Entity
@DiscriminatorValue("comment")
class Comment extends Content {
// a link to the content item
// on which this comment was made
@ManyToOne
@JoinTable(name="comment_content")
Content content
}
That's it.
