I am the co-owner/developer of a software consulting and products company. I have been making a living off of Java since 2005 and during that time I've worked on large government projects, designed and build high-volume e-commerce platforms, and worked on a variety of business applications with dozens of technologies Carey is a DZone MVB and is not an employee of DZone and has posted 10 posts at DZone. You can read more from them at their website. View Full User Profile

Problems with ORMs Part 2 – Queries

  • submit to reddit

In my previous post on Object-Relational Mapping tools (ORMs), I discussed various issues that I’ve faced dealing with the common ORMs out there today, including Hibernate. This included issues related to generating a schema from POJOs, real-world performance and maintenance problems that crop up. Essentially, the conclusion is that ORMs get you most of the way there, but a balanced approach is needed, and sometimes you just want to avoid using your ORM’s toolset, so you should be able to bypass it when desired.

One huge flaw in modern ORMs that I see though is that they really want to help you solve all your SQL problems. What do I mean by this why would I say this is a fault? Well, I believe that Hibernate et al just try too hard and end up providing features that actually hurt developers more than they help. The main thing I have in mind when I say this is query support. Actual support for complex queries that are easily maintained is seriously lacking in ORMs and not because they’ve omitted things — it’s just because the tools they provide don’t use SQL, which was designed from the ground up for exactly this purpose.

Experiences in Hibernate

It’s been my experience that when you use features like HQL, frequently you’re thinking about saving yourself a few minutes up front, and there’s nothing wrong with this in itself, but it can cause serious problems. It’s my experience that frequently you end up wanting or needing to replace HQL with something more flexible, either because of a bug fix or enhancement, and this is where the trouble starts.

I consider myself an experienced developer and I pride myself on (usually) not breaking things — to me, that is one of the hallmarks of good developers. When you’re faced with ripping out a piece of code and replacing it wholesale, such as replacing HQL with SQL, you’re basically replacing code that has had a history that includes bug fixes, enhancements and performance tweaks. You are now responsible for duplicating every change to this code that’s ever been made and it’s quite possible you don’t understand the full scope of the changes or the niggling problems that were corrected in the past.

Note that this also applies to all the other query methods that Hibernate provides, including the Query API, and through extension, query support within the JPA. The issue is that you don’t want a solution that is brittle or limited that it has to be fully replaced later. This means that if you need to revert to SQL to get things done, there’s a good chance you should just do that in the first place. This same concept applies to all areas of software development.

So what do we aim for if the basic querying support in ORMs like Hibernate isn’t good enough?

Criteria for a Solid ORM

Bsaically, my personal requirements for an ORM come down to the following:

  • Schema first – generate your model from a database, not the other way around. If you have a platform-agnostic way of specifying DDL for the database, great, but it’s not a deal-breaker. Generating a database from some other domain-specific language or format helps nobody and results in a poorly designed schema.
  • SQL only – if you want to help me avoid writing code, then generate/expose key-based, etc. lookups for me. Don’t ask me to use your query API or some new query language. SQL was invented for queries, so let me use the right tool.
  • Give me easy ways to populate my domain objects from queries. This gives me 99% of what I’ll ever need, while giving me flexibility.
  • Allow me to populate arbitrary Java beans with query results – don’t tie me into your registry of known types.
  • Don’t force me into using a typical transaction container like the one Hibernate or Spring provides – they are a disaster and I’ve never see a practical use for them that made any sense. Let me handle where connections/transactions are acquired and released in my application – typically this only happens in a few places with clear semantics anyway. This can be some abstracted version of JDBC, but let me control it.
  • No clever/magic behaviour in my domain objects – when working with Hibernate, I spend a good time solving the same old proxy and lazy-loading issues. They never end and can’t be solved once-and-for-all which indicates a serious design issue.

Though these points seem completely reasonable to me, I’ve not encountered any ORMs that really meet my expectations, so at Carfey we’ve rolled our own little ORM, and I have to say that weekend projects and just general development with what we have is far easier and faster than Hibernate or the other ORMs I’ve used. What does it provide?

A Simple Utilitarian ORM

  • Java domain classes are generated from a DB schema. There’s no platform-agnostic DDL yet, but it’s on our TODO list. Beans include support for child collections, FK references, but it’s all lazy and optional – the beans support it, but if you don’t use them, there’s no impact. Use IDs directly if you want, or domain objects themselves. Persistence handles persisting dirty objects only, and saves are only done when requested – no magic flush behaviour.
  • Generated domain classes are for persistence only! Stick your business logic, etc. elsewhere.
  • SQL is used for all lookups, including primary key fetches and foreign key relationships. If you need to enhance a lookup, just steal the generated SQL and build on it. Methods and SQL is generated automatically from any indexed column so they are all provided for you automatically and are typesafe. This also provides a warning to the developer – if a lookup is not available in your domain class, it likely will perform poorly since no index exists.
  • Any domain class can be populated from a custom query in a typesafe manner – it’s flexible but easy to use.
  • Improved classes hide the standard JDBC types such as Connnection and Statement for ease of use, but we don’t force any transaction semantics on you, and you can always fall back to things like direct result set handling.
  • Some basic required features like a connection pool, database metadata, and soon, database slave failover.

We at Carfey don’t believe we’ve created some incredible new ORM that surpasses every other effort out there, and there are many features we’d have to add if this was a public project, but what we have works for us, and I think we have the correct approach. And at the very least, hopefully our experience can help you choose how you use your preferred ORM wisely and not spend too much time serving the tool instead of delivering software.

As a final note, if you have experience with ORMs that meet my list of requirements above and you’ve had good experiences with it, I’ve love to hear about it and would consider it for future Carfey projects.


From http://www.carfey.com/blog/problems-with-orms-part-2-queries/

Published at DZone with permission of Carey Flichel, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)



Mladen Girazovski replied on Wed, 2012/02/15 - 7:47am

Personally, i did not have most of your Problems with ORMs (Hibernate/EclipseLink) and i've been using Hibernate since early 2007 (personally i prefer EclipseLink).

In fact, your criterias for an ORM are more or less the opposite of what i prefer.

I prefer declerative transactions, like Spring/EJBs offer them, also, in a greenfield project, i create the DB Schema from the domain model (you can adjust it before generating the DB from it), my Entites do not necessarily need to be "dumb" datastructures with no logic in them.

EclipseLink and Hibernate  do offer SQL Queries called NativeQueries if you need them, but most of the time they shouldn't be requiered.

Btw.  LazyLoadExceptions with Hibernate do in fact indicate an design error, not with hibernate but the way your app uses it.


Fabien Bergeret replied on Wed, 2012/02/15 - 8:11am

Hibernate can truely be a nightmare! Because many people suppose that you don't need to know SQL to use Hibernate, because many people trust the default Hibernate behaviour too much. Because it's to so easy to make crappy code ...

For all these reasons, I prefer Spring JDBC, with its RowMappers, that lets you map your ResultSet to POJOs, with the SQL plainly readable. If the developer is not sure of his query, he'll ask the DBA for help, and not try to tweak Hibernate upside down in order to have the appropriate behaviour (which is no longer correct, at least from the performance point-of-view when the DB size gets closer to production size).

Hibernate is very powerful, and can improve greatly the productivity in the upstream activities (coding), but it can also impair it a lot in downstream activities (integration, testing, tweaking) where the cost is much heavier on the project. 

Dan Howard replied on Wed, 2012/02/15 - 11:12am

Great post! In our case we rolled our own ORM because at the time Hibernate was not mature enough - about 10 years ago. Recently I wrote a nice new ORM for .NET and Java call PINF (Persistence Is NOT Futile). It's a tiny wood simple, zero-configuration, auto discovery, convention over configuration ORM library. I haven't published it yet because of lack of time for testing and documenting everything for public consumption but I am using it in production applications. If you want any extra info you can always contact me at: sproket AT videotron DOT ca.

Vic Cekvenich replied on Thu, 2012/02/16 - 6:40am

You still using SQL? Try Mongo.

You still using Java? Try Node.js.


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.