I prefer OJB, which its authors say stands for ObJectRelationalBridge (you have to use your imagination).
The main reason I prefer OJB is its object-oriented querying mechanism, versus the HQL of Hybernate. If crafting SQL strings is a hassle, why is crafting HQL strings any better?
The example from the article, Find Orders within a price range, would look like this in OJB:
broker = PersistenceBrokerFactory.defaultPersistenceBroker();
Double lowPrice = new Double(args);
Double hiPrice = new Double(args);
Criteria criteria = new Criteria();
criteria.addLessThan("priceTotal ", hiPrice);
QueryByCriteria query = new QueryByCriteria(Order.class, criteria);
Collection results = broker.getCollectionByQuery(query);
Adding additional criteria is simple. For instance, we may also want to query on orders with a certain product name, but only if the user entered such criteria on a form. With HQL, this would involve sometimes akward string concatenation, which is one of the things I like an O/R tool to help me escape! In OJB, you'd just have to write code like:
if (productName != null && productName.length() > 0)
If you're familiar with Enterprise Object Framework (EOF, part of WebObjects), this style will be familiar to you.
OJB also supports ODMG and it's Object Query Language, as well as a reference JDO implementation. Frankly, I wish they'd drop both and focus on just the PersistenceBroker API (used above). A more focused approach would allow them to get OJB out of release candidate status and to a final release.
Check it out!