I finally got a chance to try out upgrading to Hibernate 3 at work. It wasn't the smoothest of rides, but I got there in the end.
First, some background: the project I'm working on has about 40,000 lines of production code. There are about 100 mapped Hibernate classes. This isn't small by any means.
The upgrade process went as follows:
- Drop in the new version of Hibernate, and the support files that I needed (antlr, asm, cglib, dom4j, commons-collections and commons-logging). Hunting down which ones I needed to update was painful, but that was more due to the project structure than anything to do with Hibernate.
- Do a quick "search-and-replace" for 'sf.net.hibernate' to 'org.hibernate'. Fixed up a handful of changed packages manually (e.g. net.sf.hibernate.expression to org.hibernate.criterion)
- Changed the cache provider to be the Hibernate-supplied version of EHCache
- Compile, and be amazed at how many times we used the "old" ways of querying and deleting1
- Fix all of those. This was fairly mechanical, and I'll elaborate later.
At this point I had a clean compile, and I was ready to run my unit tests. And that's when I started hitting issues. So here's the list:
- There were a lot of classes with private zero-arg constructors, especially on dependant or releated objects. None of these would load in Hibernate 3. The reason, as it turns out, is that classes are now "lazy-loaded" by default in Hibernate 3; that is, the object is used as its own proxy. Previously, the default was no proxy and non-lazy. Lazy loading is good, but it meant that you needed constructors that were at least package-level; private constructors don't work for some reason. I had about 20 of these, and I couldn't find an explanation anywhere; eventually, I logged it as a bug, and Gavin King gave me the explanation. Almost invariably, BTW, I want the lazy-load behaviour; I'll live with package-level zero-arg constructors (though I would prefer private).
- Loading my mapping configuration took ages; creating a configuration and session factory went from ~25 seconds to about 2 minutes. This had me puzzled, but hunting around the Hibernate forum lead me to this post. Sure enough, I'd forgotten to update the DTD line in the configuration and mapping file and the delay was caused by repeated resolution of the DTD. This was followed by much self-kicking. Remember to update your mapping files to use the right DTD! (With the right DTD, it took about 16 seconds)
- I had some broken HQL around deletes; it turns out that the Hibernate authors had decided to drop support for aliases in HQLs for delete. So
delete from Foo foo where foo.active = falsedoesn't work whiledelete from Foo where active = falsedoes. Personally, I found this really annoying. - There's bugs in the HQL parser around the use of static constants. In the Hibernate 3.0 release, java.lang.Character constants aren't inserted in the HQL correctly. [Fix will be released in 3.0.2]
- Deleting entities in one-to-many or many-to-many relationships didn't work because Hibernate didn't delete the related rows.
- Deleting subclasses didn't work at all; some sort of HQL parser error. [Fix was released in 3.0.1]
Due to these issues, I've put on hold any further investigation into upgrading Hibernate until they're resolved. OTH, they do get resolved fast: the HQL with characters constants had a (partial) fix the next day (thanks Gavin).
My recommendation: try it and see. There's a lot of promise, it's mostly stable, and the Hibernate folks do push bug fixes out fast. If you hit a problem, report it and get it fixed.
----
1 The find(), delete(), etc, methods on Session
Comments (12)
The issues you were stumbling on are documented in the Hibernate3 Migration Guide.
Posted by Christian | April 19, 2005 3:26 PM
Posted on April 19, 2005 15:26
Um, no Christian, they're not really, with the exception of the DTD one, which was my oversight. At best, there's a throw-away reference with no real mention of the cost (e.g. the reference to classes being lazy by default is there, but no mention of what a class being lazy actually means). In other cases, I found out the information after scouring the forums (for example, the fact that aliases are not supported in delete or update queries anymore, having been dropped in a release candidate)
The first list is how far the migration guide (which is mostly excellent, BTW). The second list is the problems I had.
Feel free to quote the guide to prove me wrong, however. Or better yet, please take this feedback from someone who read the migration guide (which is a work in progress, after all) in detail, and update it to help other people not encounter these issues.
Posted by Robert Watkins | April 19, 2005 3:44 PM
Posted on April 19, 2005 15:44
Actually, 3, 5, and 6 are nothing to do with the upgrade to HB3, since they refer to new functionality that did not exist in HB2. 3 and 5 are not bugs, they are correct behavior as per JSR-220. 6 is a bug that existed in 3.0final and that was already fixed and released in 3.0.1 when you submitted your bug report to JIRA and wrote this blog entry.
1 and 2 are, IMO, very adequately covered in the Hibernate documentation and migration guide. Since you ask for it, here is the quote: "Update the DTD reference in your hbm XML files. Change http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd to http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd in the DOCTYPE."
4 was an actual bug in the new query parser that is now fixed in CVS. (Use of Character-valued rather than String-valued constants in HQL is a somewhat obscure case.) Clearly, you could have worked around this problem by following the advice of the migration guide that "if you have problems with the new query parser, switch back to the classic parser with a property setting".
Really, I think the tone of this blog entry is quite unfair.
Posted by Gavin | April 20, 2005 12:50 AM
Posted on April 20, 2005 00:50
I hate wasting my time like this, but here you go:
1. In reference documentation for years, proxies need package visible constructors always. This is nothing new or underdocumented by any means.
2. Clear in migration guide.
3. We didn't drop aliases! We implemented a completely new functionality called Bulk update/delete, for EJB3. Documentation for this can be found in the EJB3 specification drafts (and a pointer to this in the latest Hibernate reference docs, for all who don't read API docs).
4. Yeah, a bug.
5. Again, this is a new feature for which you did not read documentation. It works as expected even if this is not what you need.
6. Known limitation of a new feature, always documented in JIRA, now in 3.0.1 also in the reference docs.
Instead of ranting on your blog, why not post a comment on the migration guide page if you still feel something is missing?
Posted by Christian | April 20, 2005 12:53 AM
Posted on April 20, 2005 00:53
Have you guys been drinking the JBoss Kool-Aid? I did not see this post at all as a negative rant, but rather as a useful bit of information. I've been toying with the idea of upgrading on several projects but wanted to hear about some real experiences first. This was a great step in that direction. The author also took a pretty positive outlook towards Hibernate. To call it a rant is a bit paranoid, distasteful, and quite frankly, not what I would have expected from either of you (based on everything I've read in the past).
Posted by Drew | April 20, 2005 3:16 AM
Posted on April 20, 2005 03:16
I agree that this was not a rant.
I disagree that this was an accurate representation of the difficulty of migrating to HB3 (given that half the listed issues relate to a feature - bulk delete - that did not exist in 2.1), and one is explicitly documented in the migration quide. And I disagree that "mostly stable" is a fair characterization of the current release. (Yes, of course some new functionality has bugs, but all HB2 functionality, including the classic query parser is still there and very stable.)
I dunno, I always get suspicious (and yes, a bit "paranoid") of people posting semi-accurate stuff in blogs. There are, IMO, other more constructive places such as the Wiki - in this case, comments on the migration guide page would be very much appreciated.
Posted by Gavin | April 20, 2005 6:17 AM
Posted on April 20, 2005 06:17
Gavin,
I see bulk delete as an enhancement of the Session.delete method that was deprecated. In fact, the way I migrated was to change calls like this:
getSession().delete("Foo");
to:
getSession().createQuery("from Foo").delete();
When I find the behaviour has changed substantially, above and beyond the documented performance improvement, I call that an issue to be aware of. As the migration guide explictly states to use DELETE queries instead of the delete method, I felt that this was a stumbling block.
Not a problem: a stumbling block. That is, a change in behavior that suprised me, which I didn't feel (for whatever reason) adequately aware of, and which I didn't expect. That's why I called it an issue.
(Oh, and I agreed that the DTD thing was my snafu)
Posted by Robert | April 20, 2005 7:01 AM
Posted on April 20, 2005 07:01
Oh, and for some reason, my login to the Hibernate forum doesn't work for the Hibernate wiki - so no commenting possible.
Posted by Robert | April 20, 2005 7:05 AM
Posted on April 20, 2005 07:05
Christian: you dropped support for aliases. In a pre-release version, update and deletes had support for aliases. The release didn't. There's even posts about it on the forums.
In implementing this "brand new feature", you deprecated similar (but not equivalent) features. The delete() method on Session understood aliases. This made it really easy to share common HQL.
Now, you have support for aliases everywhere that HQL is used, except in executeUpdate().
Oh, and as was seen with the subclasses problem (apparently fixed in 3.0.1 - I said you guys were fast!) you had code still in the system that was expecting aliases.
Again, this was an issue for me. I meant I couldn't simply do a quick search-and replace for the delete() method to change it to the new calling style: I had to sit down and modify each delete call so that the HQL would work. And there was no hint in the migration guide that I would need to; in fact, there was the strong implication that the queries would be easily migrated.
Posted by Robert | April 20, 2005 7:11 AM
Posted on April 20, 2005 07:11
Gavin,
You took me to task on one of the bug entries about being annoyed that I have to go off and read the EJB3 documentation to understand how Hibernate works. Your exact quote was "You are using free software. You have no right to get annoyed about anything. End Of Conversation."
In general, I agree. However, at the same time, you don't have the right to complain about the fact that I published my opinions and experiences (which were not overly negative) in a forum outside of the approved venue of the Hibernate forums or Wiki. It goes both ways.
Posted by Robert | April 20, 2005 7:15 AM
Posted on April 20, 2005 07:15
Don't use Firefox, it has a broken cookie mechanism.
Posted by Christian | April 20, 2005 8:14 PM
Posted on April 20, 2005 20:14
Thanks, Christian. After finding exactly where my IE icon had got to, I've posted this as feedback to the migration guide.
Posted by Robert | April 20, 2005 9:21 PM
Posted on April 20, 2005 21:21