I've seen three or four ORM tool comparisons in the last three weeks; on some weblogs, on our
forum and I've even been part in several decisions.

I have the impression that many developers have problems categorizing and evaluating ORM tools, no
matter if its Hibernate, Cayenne, PrIdE (I hope that spelling is correct), or some home-made JDBC
framework. I got really frustrated at some point, but what brings me to this blog
entry is probably a posting made today, by Scott Ferguson.
He compares EJB CMP, JDO, and Hibernate. I wasn't really happy with his list of points.
Don't get me wrong, I'm not complaining about Scott's conclusions (our precious
Hibernate!), in fact, I actually usually listen to Scott. I've even followed Resins development
closely several years ago, nearly got it approved for a medium-sized installation (politics...),
and even reported and fixed some bugs.

So, this entry, after a long introduction, is about comparing ORM solutions. What all the
reviews and articles had in common was a very very obscure criteria schema. In one article,
I've seen someone comparing loading and saving a single object and looking at the lines of
code that you need for this operation. Next, we hear something like my ORM should work with
objects or other vague statements that, in practice, probably not help you decide what you should
use.

I did my research for Hibernate in Action, and I think we have found an excellent taxonomy
for ORM solutions. Actually, Mark Fussel
started to use these categories in 1997, we merely rewrote his list and set it in context to
Java application development:

Pure relational

The whole application, including the user interface, is designed around the relational
model and SQL-based relational operations. Direct SQL can be fine-tuned in every
aspect, but the drawbacks, such as difficult maintenance, lack of portability, and
maintainability, are significant, especially in the long run. Applications in this category
often make heavy use of stored procedures, shifting some of the work out of
the business layer and into the database.

Light object mapping

Entities are represented as classes that are mapped manually to the relational
tables. Hand-coded SQL/JDBC is hidden from the business logic using well-known
design patterns (such as DAO). This approach is extremely widespread and is successful
for applications with a small number of entities, or applications with generic,
metadata-driven data models. Stored procedures might have a place in this kind
of application.

Medium object mapping

The application is designed around an object model. SQL is generated at build
time using a code generation tool, or at runtime by framework code. Associations
between objects are supported by the persistence mechanism, and queries may be
specified using an object-oriented expression language. Objects are cached by the
persistence layer. A great many ORM products and homegrown persistence layers
support at least this level of functionality. It's well suited to medium-sized
applications with some complex transactions, particularly when portability between
different database products is important. These applications usually don't use
stored procedures.

Full object mapping

Full object mapping supports sophisticated object modeling: composition, inheritance,
polymorphism, and persistence by reachability or a more flexible transitive
persistence solution. The persistence layer implements transparent persistence; persistent
classes do not inherit any special base class or have to implement a special interface. The
persistence layer does not enforce a particular programming model for the domain model
implementation. Efficient fetching strategies (lazy and eager fetching) and caching
strategies are implemented transparently to the application. This level of functionality
can hardly be achieved by a homegrown persistence layer - it's equivalent to months or
years of development time.

In my experience, it is quite easy to find the category for a given product. In Hibernate
in Action, we also have a list of interesting questions that you should ask if you compare
ORM tools:

What do persistent classes look like? Are they fine-grained JavaBeans?

How is mapping metadata defined?

How should we map class inheritance hierarchies?

How does the persistence logic interact at runtime with the objects of the business domain?

What is the lifecycle of a persistent object?

What facilities are provided for sorting, searching, and aggregating?

How do we efficiently retrieve data with associations?

In addition, two issues are common to any data-access technology. They also
impose fundamental constraints on the design and architecture of an ORM:

Transactions and concurrency

Cache management (and concurrency)

Find the answers to those questions, and you can compare ORM software. Scott in fact started right
with the lifecycle, but he has not given enough information in his article for a real
discussion, it's mostly his opinion (which is fine on a weblog).

There are, as always in life, many solutions and not a single product, project, or specification
will be perfect in all scenarios. You don't have to try to get to the top of the list and
always use Full object mapping (and the appropriate tool). There are very good reasons to use a
Light object mapping tool (iBatis, for example) in some situations! In many situations, JDBC and
SQL are the best choice. I'm talking about a comparison at the same level, and I've made good
experience with the categories and questions I've shown above. Read the book. :)