Nov 3 2008

What makes a framework an ORM?

Posted by Joe Rinehart at 3:50 PM
13 comments
- Categories: Frameworks

Earlier today, I posted an entry asking if ColdFusion has no real ORM frameworks.  It wasn't about any frameworks in particular:  it was about terminology and concept.  In the comments, there's a lot of questions about what makes a "true" ORM and whether it's a definition worth following or a term that should be loosely applied to anything that helps out with SQL. 

In the overall world of OO, there really is a series of criteria.  ORM technology exists to solve the differences between object models and relational schemas.  Here's the generally accepted list of the problem areas to be solved (from what I can gather, feel free to point out more).

Granularity

A User may be composed of two Address objects (homeAddress and businessAddress), but the database may choose to store this in one table to avoid joins.  An ORM should be able to resolve the granularity mismatch between the two.

Inheritance

A User might be extended into MaleUser and FemaleUser each with different composed objects (avoiding obvious jokes here, but it was an easy example!).  An ORM should be able to resolve this difference, allowing a user to save the state of both User subclasses.

Polymorphism

As soon as we introduce inheritance, we obviously have to deal with polymorphism.  If a UserGroup has-many User, and we ask the ORM to find all Users that are part of the Group, it should be able to understand, discrimate between, and populate the resulting collection with User, MaleUser, and FemaleUser instances as approriate, keeping the is-a contract in place.

Identify

This one's a killer.  In an object model, it's perfectly possible to have two instances of a single object (User with Id of 314).  In the database, primary keys keep the equivalent from occuring. 

This introduces a problem of identity mismatch.  In the database, there's one definition of identity (one record, Id of 314.  In the object model, there are two:  instance identity (two instances) and entity identity (two instances, but _one_ entity, id = 314).

An ORM should be able to resolve the concept of identity within its units of work against the relational database.

Associations - Plumbing

Object models relate instances via references.  Databases do it via foreign keys.  First, an ORM must be able to solve this plumbing mismatch, usually accomplished through foreign-key-identified proxy collections / objects or lazy loading.

Associations - Navigation and Direction

A second problem with associations is directional.  An object reference is, by nature, one-way.  A foreign key association, however, is multidirectional.  An ORM should constrain the free navigability of the data model into the directions specified by the object model.

Associations - Multiplicity

It gets worse and worse for associations.  In a relational database, any foreign key reference is either one-to-many or one-to-one.  When looking at an object model, however, it is impossible to determine the multiplicity of a collection-based association property:  it could be one-to-many or many-to-many.  An ORM needs to be able to solve this mismatch, providing a solution that allows for both one-to-many and many-to-many relationships between objects to be persisted.

 

Comments

ike

ike wrote on 11/03/08 4:48 PM

I don't think I'm following what you're saying the item you describe as "identify". I understand the difference between the db's concept of identity and the OO concept of identity. But then I don't understand the problem being solved in the last sentence when you say "An ORM should be able to resolve the concept of identity within its units of work against the relational database."

I would gather that generally speaking the external ORM would introspect the provided object, find its class name and then look for a definition in its config of how that particular class is to be persisted?
Henry Ho

Henry Ho wrote on 11/03/08 5:07 PM

I guess you have used Hibernate before, so does Hibernate support everything listed above, and therefore it qualifies as a real ORM framework?
Barney

Barney wrote on 11/03/08 5:29 PM

Isaac,

The idea is that if I call User.getById(42) twice in the same persistence context, I should get the SAME object back from both invocations. I shouldn't get two different objects back, each with an id of 42. Obviously each separate persistence context gets it's own copy of User #42, but within a single context, there should only be a single instance representing that user.
Joe Rinehart

Joe Rinehart wrote on 11/03/08 7:44 PM

@Isaac,

Barney says it exactly correctly. It can get weirder and more complex: what if two instances of UserGroup each have a lazy-loaded collection of User and each collection contains references to the same user? The ORM needs to keep each collection sharing references to the same User instance while within a persistent context.

Persistence context are another concept not found in ColdFusion ORMs) - the difference between a detached object and a persistent object took me a while to understand. In the case illustrated above, if the two UserGroup instances were recalled in the same unit of work against the db, they'd both be persistent, and the shared User reference should point to the same place. However, if one UserGroup is discarded at the end of the request while the second is stored in session, the unit of work ends and the session-scoped UserGroup is considered "detached"....a subsequent request loading the same UserGroup by id could get a reference to a _different_ UserGroup (barring caching implementation).
Barney

Barney wrote on 11/03/08 7:54 PM

And don't forget gracefully handling the case where that detached UserGroup is reattached to a persistence context in the subsequent request. The framework needs to have a mechanism for dealing with that eventuality so identity isn't spoiled. Looking at it from the other side, the persistence context can seamlessly operate on currently-persistent objects regardless of whether they came into the context from reattachment or from the DB/cache.

Reattachment is a friggin' mess, no question, but in my experience it's a fairly uncommon use case. So it's totally worth dealing with it on occasion to gain the benefits of object identity in the more typical use cases. It's absolutely essential for a state-based persistence mechanism though.
Mark Mandel

Mark Mandel wrote on 11/03/08 9:02 PM

Looking through this, there is some work for Transfer to do, but some other stuff that is done:

Granularity - doesn't work
Inheritance & Polymorphism - next release
Identify - has been working for ages (and yeah, it is tricky)
Associations - works too. Although there could be some improvements, namely bidirectional m2m etc.

So slowly getting there, but there are always areas for improvement.
Gary Gilbert

Gary Gilbert wrote on 11/04/08 4:55 AM

Mark I gotta hand it to you for keeping at it. When looking at theme as complex as ORM I'm glad that I don't really have to programm something to make it work there are people like you doing all the heavy lifting for me.

Then I do a little work in Grails and practically forget about all of that stuff cause Grails just handles so much of that stuff automagically.
Jared Rypka-Hauer

Jared Rypka-Hauer wrote on 11/11/08 10:26 AM

ARF! was cool. It got us thinking.

Then Reactor, the uber-ActiveRecord implementation.

Then Transfer, the pseudo-ORM, with much yet to come.

And now CF9 is talking about Hibernate integration.

We're making progress!
Barney

Barney wrote on 11/11/08 1:26 PM

CF9. Bah. If you don't mind a little Groovy you can use Hibernate today in at least a couple different ways. I happily use it under my CFML (on CF 8.0.1 or Railo 3) with no compilation or container restarts. I don't know how the BroadChoice guys do it.
Jared Rypka-Hauer

Jared Rypka-Hauer wrote on 11/11/08 3:24 PM

I think you're missing my point tho'... I'm talking about a wholesale shift in mindset that drives not just innovation but upgrades in technique and technology. I'll grant you that there are ways to get things done that exist outside the mainstream. What I'm saying is that mainstream thought within the ColdFusion community has been iterating toward the advanced on enough of a scale to drive not just OSS projects but the inclusion of things like Hibernate in the engine itself.

We, as ColdFusion developers, as a community, are boosting our skills and our understanding... every step of the way is proof of that. That's what I'm saying. :)
Jack Smith

Jack Smith wrote on 11/19/08 3:59 AM

A second problem with associations is directional. I dont think so, As the directional must be the first thing in the building associations

http://www.laptops-battery.co.uk/ibm-thinkpad-t60-battery.htm
Howard Scholz

Howard Scholz wrote on 11/20/08 12:29 PM

Joe, saw your presentation at Max, and it seems that you are right on target in making the definitions of terms the first order of business. In the presentation, it was proposing a definition for "Enterprise" for the sake of the following hour. Here, in this discussion, you return focus to the definition of ORM to qualify different solutions' membership in the set of solution labelled ORM. I've seen Transfer and Reactor both called ORM solutions, and that can be a little confusion/misleading.
For solutions in the ORM space, their adherence to the set of qualifiers is not as important as getting the problem definitions ironed out in the first place. *Especially* since the definitions of some terms are not well understood. Failure to identify and classify the problem at hand will prevent the evaluation of any solution's effectiveness.
It's too bad that the words, and terms, like ORM grow legs and run faster than their definitions. Thanks for getting people (read: me!) to think about these things, and really analyze the appropriate use for technology.

Howard
cheap wow gold

cheap wow gold wrote on 12/21/08 1:11 AM

Nice job! Thanks for your information.

Write your comment



(it will not be displayed)