I've been using Hibernate sans Java EE for about four years. I started using it under JPA (again, without Java EE) about two years ago. Only in the last few months have I been able to deploy a Java EE environment, and there, only for a very small project, and the Java EE aspect was pretty minor, although desirable and cool.

Hibernate does not require Java EE stuff. The "dynamic weaving" is provided by Javassist (formerly provided by cglib, but cglib is apparently deprecated). No complex setup here. Put the appropriate dependency in your pom and it "magically" works.

Indeed, my biggest objection to Hibernate is the degree to which it relies on magic. A lot of that magic is truly magic, in the sense that you are not supposed to worry to hard about how it all works. If it did always just work, it wouldn't be maddening when you try to figure out why it is going wrong only to get slapped in the face by a fistful of hard magic.

For instance, the batch annotation, in pure, non-JPA Hibernate, is the fetch "mode." There are several options like "join" and "subselect." Hibernate defaults to an N+1 queries situation, but supplying "join" or "subselect" instead isn't necessarily good enough to get the behavior you want. We had a situation where no matter what we did in the Hibernate config, the behavior was an N+1 query explosion. The problem turned out to be an innocuous-looking log statement in the object model. Tracing in, it turned out that this log statement was being invoked indirectly from the object's constructor, causing the list to be "forced" before construction was complete. For some reason this bypassed Hibernate's usual configuration. The solution was to delete the log statement and take a lot of care not to touch anything that might be a PersistentList from the constructor.

That kind of lesson, while trite, is very hard to apply in practice. Especially when you have a set of developers working on the database and object-relational mapping layer and another set working on the model. Hibernate brings a lot of "gotchas." Shield's article hits on one of the more onerous database-side ones, that you are informally forced into using artificial keys, but there are enough oddball ramifications and restrictions to go around that plenty of them spill out into the Java code.

I have positive feelings towards myBatis, but I have only used it for a few edge cases in my Hibernate projects. While it is actually pretty easy to trick Hibernate into returning real objects for native queries, the trouble doesn't end there. It's very hard to do a complex SQL query from Hibernate without running into the vague sensation that the Criteria API would be better. A few hours later, you're back to building SQL strings, having read unsettling absurdities in the documentation like "There is no explicit 'group by' necessary in a criteria query."

myBatis's major advantage, in my conjectural opinion, is that it does not pretend to liberate you from worrying about the database. As a database developer, I am free to write the best query I can for a given situation, liberally using the most esoteric features of my database. My peers in the model can write exactly the interfaces they want to use. But they are not free to imagine that they have the entire object graph available to them to manage to the minutia at all times, and the ramifications of this loss on a group working solely in the model must be great, and I haven't seen them yet. I see storm clouds looming on that side of this tradeoff. It's annoying when I go to a peer and say what they can and cannot do in a constructor or a bean property getter/setter, but from then on they can still pretend that they have everything, and the worst thing that happens is really untenable performance. But everything works. myBatis, in contrast, is only too happy to give you back an incomplete object tree. There is no "weaving" or "instrumentation" in what comes back to support on-the-fly querying just because you accessed some property. Again, it is a great strength (much, much less magic) but it's also a great weakness. Your model guys aren't going to be able to ignore the database with impunity.

I'd like to hear from a group that switched from Hibernate or JPA to myBatis and how it worked out.