Help

I've seen lot's of people writing (or using) third party abstraction frameworks on top of ORM solutions like Hibernate so that they can potentially get rid of one ORM engine to another (or even an other technology). Such frameworks are even considered by some architectsas a must-have.

Praiseworthy, but raising more issues than fixing ones. When you abstract technologies like Hibernate to make them portable, you end up sacrificing lot's of power and functionalities. Simply because semantics are slightly different from one engine to an other.

Let's play with statistics:

  • in 1% of the applications, the need for a switch from one ORM engine to an other arise
  • in 99% of the applications, the need for one or several advanced features of ORM arise

You should focus on using and knowing your ORM engine and not on spending time in writing (or using) an abstraction framework.

When using abstraction frameworks you haven't written, other kind of problems actually show up.

When your ORM engine introduce new APIs or new features, you have to wait for the abstraction framework to release accordingly making you dependent on someone else's agenda.

You no longer know (either by heart or at all) the actual method abstraction (or semantic alteration) introduced on top of your ORM engine. This user learnt it the hard way (and he is unfortunately not alone), Spring's /HibernateTemplate/ wraps the Hibernate methods without even giving you a hint about the actual semantic.

The only proper abstraction between an ORM engine and another is a common specification they adhere to. This is one of the reasons why JPA (EJB 3.0) has been introduced. Why is it the only way? Because a specification describes in a very detailed way the common semantic the various ORM engines have to follow.

So please, think twice before using some random proprietary abstraction framework (open source or not). They usually bring no value add but increasing bug areas... Specifications are here to solve the engine abstraction problem (but once again, this is a concern in very few applications).

PS in case someone is misleading, I'm not arguing against DAO layers

33 comments:
 
26. Jul 2006, 14:27 CET | Link
Mr Coffee
Another Spring rant. Boring.

Mr C.

ReplyQuote
 
26. Jul 2006, 19:23 CET | Link
Mike
I agree with Emmanuel.

Recently I did a migration from JDO to Hibernate for quite a big application of my customer. We used some kind of abstraction (for fallback) but we made sure that the developer was able to work directly with the APIs of Hibernate / JDO.


 
26. Jul 2006, 20:32 CET | Link
"Another Spring rant. Boring."

I'm not interested in that. Besides that, there is a lot of home grown frameworks falling into this category which are hurting ten times more.

Look at it from my side.
"Another user screwed. Boring."
 
26. Jul 2006, 20:59 CET | Link
Daniel Serodio
Statistics already have a bad enough name, let's not call some numbers pulled out of your hat "statistics", shall we?
 
26. Jul 2006, 22:08 CET | Link
Paul Barry | mail(AT)paulbarry.com
Yeah, I agree with Daniel. I can make up random statistics too:

1% of all applications actually need to change what RDBMS software they use

99% of all applications actually need to make use of RDBMS specific features

Therefore, using an ORM framework to abstract the SQL instead of using JDBC or something else to write vendor specific SQL is a bad idea.

PS - I'm not truly advocating this position, I'm just showing how using unfounded statistics can spin an argument

PPS - How can you say this is not a spring rant when you specifically point out Hibernate Template?
 
26. Jul 2006, 22:16 CET | Link
Dave
I absolutely agree that abstraction layers created for their own sake are a whole load of evilness. Hibernate is an abstraction layer in and of itself, and there is simply no need to abstract it away unless you are 100% sure you are going to support other, similar abstractions at some future point. The fact is, hibernate is at its most powerful when you can assume it will always be there and have direct access to its API.

However, I disagree that the specific example is evil. The HibernateTemplate is not an abstraction to shield you from hibernate - rather it encapsulates a lot of boilerplate stuff that you generally end up doing anyway. You have to understand the semantics of Hibernate in the first place in order to use it. Granted, if the Spring guys are going to duplicate the methods on Session, they ought to ensure the documentation is in synch, and the difference in this specific case is two words:

HibernateTemplate.Load():
Returns:
    the persistent instance

Session.load():
Returns:
    the persistent instance or proxy

However, HibernateTemplate does state that the user should read the documentation for Session. The fact is that the user did not know that load returns a lazy proxy (if possible), whereas get doesn't, and they could not figure this out from a stacktrace, or read it in the documentation. And frankly, if a user is having problems with HibernateTemplate, they should take this up in the Spring forums.

To summarise,
Pointless abstraction == bad
HibernateTemplate != pointless (or an abstraction, really)
 
26. Jul 2006, 22:29 CET | Link
Christian
"The HibernateTemplate is not an abstraction to shield you from hibernate - rather it encapsulates a lot of boilerplate stuff that you generally end up doing anyway."

Such as?

All I can see is that the Spring templates for Hibernate convert RuntimeExceptions into other RuntimeExceptions, a completely useless "feature". Even worse, the JpaTemplate which is based on the same ideas of lock-in, converts standardized exceptions into proprietary exceptions.


 
26. Jul 2006, 22:35 CET | Link
Christian
It is also worth mentioning something from the real world out there. I sometimes see customers I'm consulting use the Spring templates on top of Hibernate.

If I ask the developers or architects why they did this, the only real answer I hear is "we thought that we have to". Of course, the next step is to rip out this artificial lock-in API and write plain Java with Hibernate. This usually results in less lines of better code.

(And yes, I do the same if its not the Spring templates but some other unnecessary abstraction layer.)
 
26. Jul 2006, 23:52 CET | Link
Darcy Schultz
I made a couple similar comments in my Blog:

http://cocoalocker.blogspot.com/2006/03/suffering.html
http://cocoalocker.blogspot.com/2006/05/daos-and-orms.html

As for Spring, all I can say is that I've only had the displeasure of using it once on my last project. Perhaps there are more appropriate ways to use this framework but I'll be very cautious about wading into those waters again.

As for DAO's, well I don't think they're always necesssary either, but that's a bit more controversial.

All in all, great rant!
 
27. Jul 2006, 01:17 CET | Link
Anonymous Guest
Christian,

Please enlighten an uninformed soul. Could you give a before - after comparison of code using Spring's HibernateTemplate and pure Hibernate? I would like to see the difference and it sure would put a lot of weight to your argument.

Cheers!
 
27. Jul 2006, 01:42 CET | Link
Christian
I really have to do this? In fact, I already showed code with and without Spring on the infamous "Hibernate with Spring" Wiki page that was on our community wiki. Unfortunately, Juergen wanted the page to be removed after my edits.

I don't feel like doing this again and I can just imagine the personal insults I would get from this.

In fact, it should not be my (or any other Hibernate developer's) job to show how Hibernate is easier to use without wrapping over the API. We are not the right people to ask here, unless it is on our website or users are lost on our forums.

It is the job of the designers who introduces a wrapper to clearly show what the concrete benefits of such a wrapping, if any, are.


 
27. Jul 2006, 02:22 CET | Link
To Daniel
I wrote that while watching Mad Max on TV, so yes statistics comes from my own (and my customers) experience. I used the expression "play with" ;-) More seriously I do stand on my position, ORM switch is orders of magnitude less common than using advanced features of an ORM.


To Paul
You might be right about the statistics on DB, but the point is that the *value add* of ORM is significant enough to worth the price.
I pointed to this example because that's the last user I helped on such a case. And people using home grown layer usually know it, thus do not fall in this kind of error.


To Dave and GB
There is no boilerplate to hide. look at the HibernateTemplate code, it delegates straight to Hibernate methods (or hide some Spring boilerplates). Just look that's open source :-)
And that's usually the same for home grown framework I've seen (and even developed in the past)

Mr C.
There is no FUD in what I've said, I've backed up my claims. Your multi ORM/DAO encapsulation of the underlying SQL error doesn't stand:
 - my argument about you not moving often from one ORM to an other
 - the fact that if you move from one ORM to an other I guess you also want to move from one encapsulation to an other, making the encapsulation useless in the first place.

And coffee kinda sucks in ATL, to be honest.



There has been some constructive feedbacks, that the whole point of this entry: do think about the usefulness of a layer before adding it. That's true for ORM too, which we never denied.
 
27. Jul 2006, 02:54 CET | Link
Mr Coffee
"No, there is not a single one. If you have one, name it instead of making this vague statements."

I use two different data access solutions in a project. It is nice to be able to capture consistent DataAccessExceptions from both JDBC and Hibernate that contain the same error info without having the upper layers of my app needing to know specifics about the specific ORM/DataAccess solutions used.

There. I gave you a concrete use case.

"Right, I use a weirdo Spring API to get JPA "support".

Using PersistenceAnnotationBeanPostProcessor is a simple matter of defining the bean in your spring context definition. It's like flipping a switch in your configuration and after that you can use the EM annotations. Comparable to to creating a deployment descriptor in JBoss for example. You must be famiar with that, ey?

There is no Weird Spring API involved. Again, this is FUD based on having no clue how Spring actually works. Here is a quote from the documentation:

"It is possible to write code against the plain JPA without using any Spring dependencies, using an injected EntityManagerFactory or EntityManager. Note that Spring can understand @PersistenceUnit and @PersistenceContext annotations both at field and method level if a PersistenceAnnotationBeanPostProcessor is enabled."

More info in the manual, I suggest you check it out before making more false claims about Spring.

12.7.3. Implementing DAOs based on plain JPA: http://static.springframework.org/spring/docs/2.0.x/reference/orm.html#d0e15210

"Yes, because these are EJB 3.0 annotations that come with every EJB 3.0 container."

Funny how you guys dare to talk about lock-in. Lock-in happens everywhere, especially in the app server or ORM world where the Holy Standard is always mediocre and thus you end up using proprietery extensions.

But most importly, not everybody wants to buy into the EJB3 thing. For many of us using a simple lightweight container to glue POJOs together is fine. That is where Spring comes in.

"... that there really is no technical reason why one should use a template over Hibernate"

I just gave you one. If you don't want to use the HibernateTemplate stuff then just use the plain Hibernate3 API. Again, described in the manual.

12.2.5. Implementing DAOs based on plain Hibernate3 API: http://static.springframework.org/spring/docs/2.0.x/reference/orm.html#d0e13475

See, that is the whole problem, you guys seem to hate a great framework because you have NO CLUE about what it can do and have only experienced it at customers that made the wrong design decisions.

Kind of a narrow view in my opinion. Bad design happens everywhere. In plain Hibernate projects, in EJB3 projects and in Spring projects. Big surprise.

Too bad the coffee sucks in Atlanta.

Mr C.

 
27. Jul 2006, 03:13 CET | Link
Anon
Mr Cofee, I think the "Weird Spring API" they are talking about is HibernateTemplate.
 
27. Jul 2006, 03:23 CET | Link
Christian
"I use two different data access solutions in a project. It is nice to be able to capture consistent DataAccessExceptions from both JDBC and Hibernate that contain the same error info without having the upper layers of my app needing to know specifics about the specific ORM/DataAccess solutions used.

There. I gave you a concrete use case. "

No, you didn't. Why would any upper layer need a single DataAccessException? So you can print nicer looking fatal error messages?

For the rest of the stuff you wrote... I am well aware how Spring works. And yes, I was teasing you a little with this "Spring can inject dependencies if you run your stuff inside the Spring container". I don't really want to argue about "lightweight" containers, that is not what this blog entry was about.

It's however good that you brought it up because it shows the real issue.

The problem is that these two things are constantly mixed up. To the novice user it looks like you only get the useful feature (dependency injection) if you also introduce a useless wrapper.

Even if the Spring documentation includes one sentence to the contrary: The stack of Spring and Hibernate books on my shelf, the experience from on-site work, and the questions on the forums show a different picture.

What I am arguing here is that either the _good_ and _real_ use cases for the templates should be clearly documented, or that if none can be found these wrapper APIs should be removed because they obviously do more harm than good.

Maybe its time that somebody asks "Why would I use FooTemplate?" on a Spring forum, and you Spring users get discussion going that has a real result. Just like any development team would discuss the usefulness of a wrapper that was introduced by convention.

 
27. Jul 2006, 15:02 CET | Link
Anonymous Guest
I added the question on a Spring forum here: http://forum.springframework.org/showthread.php?t=27398

Hopefully the discussion over there will be rational, clear the misunderstandings that people have and help them make a better decision.

 
27. Jul 2006, 18:24 CET | Link
The urge abstract your way out of everything seems highly entrenched in peoples minds. The worst case I ever saw was 4 people implementing an IDE in C++. Each were building a "layer" on top of the others. Hence there were 4 window classes, 4 control classes. Add a bit of multiple inheritance to that and you can imagine a very ugly square shaped object model. Not terribly surprising the software remains largely unchanged today 12 years after the release of version 1.0

I really find the level of concern for the quality of software using Hibernate impressive. Even if I slightly disagree on some of the details here, I think its very sound advice Emmanuel gives.
 
27. Jul 2006, 21:40 CET | Link
Daniel Serodio
@GB: Just curious, did you read my thread at http://forum.springframework.org/showthread.php?t=27366 before creating a new one?

See my comment over there about Hibernate 2.1 vs 3.x
 
27. Jul 2006, 22:08 CET | Link
Christian
And even if the Javadoc from Hibernate is copied into the Spring template, it will be outdated again with Hibernate 3.2 (the semantics of get() have been changed to align with the JPA spec). This is not a solution.


 
28. Jul 2006, 15:00 CET | Link
Anonymous Guest
@Daniel: No I hadn't, but I'm glad you joined the discussion in the latest thread.

@Christian: The Spring documentation will always be behind Hibernate's (and JDO's and Toplink's) if there's no communication between all these teams - everyone follows their own independent schedule. Would it be possible for the Spring & Hibernate teams to collaborate to synchronize the documentation so that us end-users don't get screwed?
 
28. Jul 2006, 18:02 CET | Link
Dave
"The HibernateTemplate is not an abstraction to shield you from hibernate - rather it encapsulates a lot of boilerplate stuff that you generally end up doing anyway."

"Such as?"

:)

Such as automatically marking all queries as cacheable if configured to do so, or setting the FLUSH_MODE on all sessions, or applying a spring-managed entity interceptor to sessions, or (conditionally) automatically participating in an existing thread-bound session and transaction if such a beast is available. Plus the wrap-and-rethrow-runtime exception thing is not just about providing a unified data access exception hierarchy. If you are using hibernate 2, wrapping the exceptions gets old *very* quickly.

As I said, these are all *conveniences* that add value to users. They add no real abstraction - you are still working directly with the hibernate API in any non-trivial case (through the hibernatecallback mechanism) or with convenience methods that duplicate session functionality for the simple stuff.

Now, I know that some of these *extremely useful* features have been rolled into hibernate 3 to some extent. However, some of us out there had to build applications with hibernate 2.1 and spring and then continue to support them. Some of those three-year-old applications are still absolutely stable or under active development, with *zero* commercial interest in upgrading any of the core libraries. And besides, not all of those features are in hibernate 3.
 
28. Jul 2006, 18:38 CET | Link
Christian
About Hibernate telling the Spring guys when to update the documentation: No, we don't have enough time as it is and why would we do that? The information is available on our issue tracking system etc. It should be clear that no matter how much effort anybody puts into this, this strategy will never work.

And finally we are getting somewhere (the "discussions" on the Spring forum are now dead after the usual JBoss bashing...):

- Such as automatically marking all queries as cacheable if configured to do so

Useless, very very few queries benefit from caching.

- or setting the FLUSH_MODE on all sessions

Can be done with a CurrentSessionContext in Hibernate, no need to wrap the API.

- or applying a spring-managed entity interceptor to sessions

Can be done with a CurrentSessionContext in Hibernate, no need to wrap the API.

- or (conditionally) automatically participating in an existing thread-bound session and transaction if such a beast is available

Built into Hibernate with getCurrentSession() and customizable CurrentSessionContext, no need to wrap the API.

- Plus the wrap-and-rethrow-runtime exception thing is not just about providing a unified data access exception hierarchy. If you are using hibernate 2, wrapping the exceptions gets old *very* quickly.

Yeah, but Hibernate 2 doesn't matter anymore. This is about the _current_ situation and new great inventions like the JpaTemplate which creates the same problems.

- Now, I know that some of these *extremely useful*

I yet have to see a really useful feature that would justify hiding the native API of a service, binding much application code to another framework, raising the bar for learning, and exposing users to documentation and upgrade mismatches.

 
28. Jul 2006, 19:53 CET | Link
Anonymous Guest
http://houseofhaug.net/blog/archives/2005/08/12/hibernate-hates-spring/
http://www.logemann.org/blojsom/blog/default/2005/07/07/oops_JBoss_did_it_again_or_how_to_say_forget_Spring.html

Well it turns out everything (and what more) was already said on the subject, and that this discussion or the one on the Spring forum won't lead to anything constructive, so I'll just drop the issue.

Good day guys.

 
28. Jul 2006, 22:29 CET | Link
Dave
"Useless, very very few queries benefit from caching. "

So why does hibernate even offer a query caching function? Put your money where your mouth is and take it out. I on the other hand have *lots* of queries that benefit from caching, and in direct contradiction to your statement use this specific feature extensively.

"Yeah, but Hibernate 2 doesn't matter anymore."

This is a bit of a tangent now, but few things piss me off like this response. Upgrade to the latest version - its suddenly gone a bit ActiveMQ in here. Like upgrading is always an option, no questions. For green-field projects starting now, with no conflicting company policy regarding internal toolstack, of course Hibernate 3 is a shoe-in, no argument. Unfortunately, Hibernate didn't just start being good at version 3. It was quite good before, and some of us out there have to support legacy applications that were built on it. And some of us also have to commercially justify a decision to change a core part of our toolstack, with the potential ramifications for developer learning curve and stability that that entails (and going from Hibernate2 to Hibernate3 is non-trivial). For some of us out there that are building and supporting systems based on it, Hibernate 2 *matters a great deal*, so pretending it doesn't exist is laughable.

Anyway...

When working with hibernate 2, the spring template absolutely adds huge amount of value over the hibernate apis directly. This is undeniable. The fact that many of the things it does are now part of hibernate 3 to some extent is testament to that.

I take the point that the value with hibernate 3 is a little less, but your "Can be done with CurrentSessionContext" arguments are disingenuous. A typical spring app (of the kind that I and many others work on) may have several hibernate templates, all configured to set up their sessions differently. The fact that HibernateTemplate takes care of setting up the session itself, after getting it from the session factory but before you get a hold of it is entirely the point. All your "rebuttals" apply solely at the sessionfactory level and are functionally non-equivalent. I have things that I cannot do as simply as I can do them at the moment without something functionally equivalent to hibernate template.

"I yet have to see a really useful feature"
Whenever I cite one, you say its not actually useful or give me a non-equivalent feature in hibernate 3.

"hiding the native API of a service"
It depends what you mean by "hide". It gives you direct access to the native API, as I've said before, and also adds some convenience methods that mirror and enhance the native Hibernate API. As I've said before, anything non-trivial is done in the execute() method using a hibernate callback. Pretty much everything I do, I do via the methods on Session, but I obtain that Session from the HibernateTemplate because it enhances it in ways that you have to do manually if you just use Hibernate's getCurrentSession() support. It is, to my mind, exactly the opposite of the kind of abstraction framework your original post was arguing against.

"binding much application code to another framework"
Back to JDBC for me then. I thought that fear of binding your application code to a framework was one of your arguments against DAO abstraction? By the logic of this statement you're backtracking...

"raising the bar for learning"
Let's just say this is subjective. I've never worked with anyone who's found the hibernate parts of Spring difficult to learn, especially when compared to learning Hibernate. In fact the reverse has been true in all cases. You on the other hand get all kinds of dumbass questions in the user forums which may give you a different perspective. We'll never agree here because our practical experiences differ wildly.

"and exposing users to documentation and upgrade mismatches"
See now, I agree with the documentation one. The Spring guys should just point everyone at hibernate docs for the duplicated session methods, rather than attempt (or, it appears, not even attempt) to keep them in sync. Not sure what you mean about upgrade mismatches though.

I don't hold out any illusions that you will be convinced, nor will I be convinced of your position. Our experience here is so obviously irreconcilable that its kind of pointless to argue about it anymore.

 
28. Jul 2006, 22:56 CET | Link
Daniel Serodio
Okay, the documentation problem is solved (http://opensource.atlassian.com/projects/spring/browse/SPR-2358).
 
28. Jul 2006, 22:56 CET | Link
Christian
"So why does hibernate even offer a query caching function?"

I wasn't talking about the usefulness of query caching, I was talking about the usefulness of enabling query caching for all queries.

"For some of us out there that are building and supporting systems based on it, Hibernate 2 *matters a great deal*, so pretending it doesn't exist is laughable. "

That is super, so use Spring templates for Hibernate 2.x if you want or have to. Nobody, the Hibernate guys included, ever said that HibernateTemplate wasn't useful for Hibernate 2.x. The simple fact that this discussion is about Hibernate 3.x and JPA seems to be difficult to grasp. Again: I don't care what great exception wrapping Spring did for Hibernate 2.x. I'm talking about _right now_ and _the future_.

"The fact that many of the things it does are now part of hibernate 3 to some extent is testament to that."

Yes, it's called evolution of software. If enough people need a feature, and it can be implemented, it will be. (Isn't it interesting that nobody every asked for stuff like "enabling the query cache for all queries" to be included in Hibernate?) This discussion, although in the wrong forum, is about the evolution or deprecation of HibernateTemplate (for Hibernate 3.x) and JpaTemplate.

"The fact that HibernateTemplate takes care of setting up the session itself, after getting it from the session factory but before you get a hold of it is entirely the point. All your "rebuttals" apply solely at the sessionfactory level and are functionally non-equivalent. "

This is exactly the use case for an extension of CurrentSessionContext. The fact that the SessionFactory has one CurrentSessionContext assigned does not mean that you can't implement a CurrentSessionContext for different purposes in one application.

Can you now please please please move this into a Spring forum and get some other people who know the Hibernate 3.x extension points to join in. Maybe one day even the Spring interceptors will use the these extension points instead of doing magic.

 
31. Jul 2006, 22:38 CET | Link
Steve Jobs
As long as Hibernate remains LGPL, developers will pick it up and use it only to have to rip it out later when their lawyers hear about it. Its happening in my company at great expense.

I agree with the premise though - pick your OR tool and stick with it.
 
01. Aug 2006, 23:58 CET | Link
Emmanuel Bernard | emmanuel(AT)hibernate.org
You can contact RedHat, they will explain to your lawyers that they fear is unfounded (which they should have undertood in the first place if they were good).
Very big companies and their respective lawyers *deeply* looked at the LGPL and Hibernate code and decided to go with it. This would not have happen if they had feared any flaw in LGPL
 
06. Aug 2006, 17:35 CET | Link
syber
I wish it wasn't too late for Emmanuel's advice .. as a consultant I have seen several (non-spring) abstraction layers for Hibernate. Usually from big, slow-moving companies trying to be "safe", but don't get me started.

*Groan* now I have to learn a homegrown solution - so much for hiring me on the basis of Hibernate experience.
 
06. Sep 2006, 21:51 CET | Link
I completely agree with this article; I have worked in a number of organisations now that have tried and introduced their own in-house frameworks that fail for one of many reasons, but primarily because a non software engineering dedicated corporate can never match the amount of work, documentation, know-how, and support of an open source framework that have dedicated people working on it continuously. The law of survival of the fitest pervades - if the open source library is useful it is worked on and continues to grow and become more encompassing, stable, and mature (e.g. hibernate, spring, etc.). Writing a framework around this work just obfuscates the original intention, error handling, interfaces, etc..
 
09. Sep 2006, 23:11 CET | Link
Pietro Polsinelli
Emmanuel,

  I could hardly agree more. Working directly with the Hib APi is a pleasure. Keep up the good job, and keep it simple.

Regards.
 
19. Sep 2006, 04:26 CET | Link
a_rico
Congratulations to all the Hibernate Team.

It's Great!
 
06. Nov 2006, 08:23 CET | Link
ironclay | m.ceste(AT)mac.com
"PS in case someone is misleading, I'm not arguing against DAO layers"

But an abstraction layer is a DAO. I argue that you should not use DAOs with Hibernate because if you ever decide to switch to another ORM, you basically have to guarantee the contract of your DAO which will probably contain lazy-loading and cascading. Just use Hibernate (with or without an abstraction layer, depending on how much control you want) in your business objects.

But I don't see Spring as an abstraction layer but as a support framework. The exception handling is similar to what you would normally write in your own application. I don't consider it an abstraction.
Post Comment