Moving day!
I decided to upgrade from Hibernate 2.1.8 to Hibernate 3.0rc1. Didn’t seem so difficult, but two problems took a considerable amount of time to figure out: the lazy=”true” by default and the new antlr query parser in weblogic.
What I did:
- Renamed packages from net.sf.hibernate to org.hibernate
- Renamed imports of org.springframework.orm.hibernate.* to org.springframework.orm.hibernate3
- Updated all references to org.springframework.orm.hibernate in the Spring XML and properties files (the database dialect e.g.) to org.springframework.orm.hibernate3
I should mention that we use org.springframework.orm.hibernate3.HibernateInterceptor.
I got this error when I started Tomcat:
“could not initialize proxy – the owning Session was closed”
According to the Spring forum, the solution for this error is to set lazy=”false” in the Hibernate mappings. Instead of doing this, I decided to remove all our calls to Hibernate.initialize() (which was needed because we need some collections in the JSPs that won’t get loaded otherwise). I replaced the AOP HibernateInterceptor with org.springframework.orm.hibernate3.support.OpenSessionInViewFilter which is an implementation of the “Open Session In View” pattern. The idea is that a Hibernate Session is opened before every request, and closed afterwards.
The “problem” with this approach is that an explicit session.flush() is needed every time you perform session.save() or session.update(). See the Javadoc for OpenSessionInViewFilter for the reason for this. It is possible to make a subclass of OpenSessionInViewFilter which flushes automatically, but this is not recommended.
The result of this lazy loading is a noticeable reduction of SQL calls (you can check this by setting the Hibernate “show_sql” property to “true”.
Another problem I encountered and that bothered me for some time, was an issue with the new Query parser in Hibernate 3, which uses antlr. The issue and the solution (hack) is described in this Hibernate forum thread. The problem is that weblogic 8 uses the infamous 33 MB weblogic.jar, which already includes a version of antlr. This causes class loading problems and an error since the antlr classes are loaded by the servers classloader and can not see the classes in hibernate3.jar which is inside an ear or a war. This nice line is given as an indication of what went wrong:
CharScanner; panic: ClassNotFoundException: org.hibernate.hql.ast.HqlToken
After this error, System.exit() is called from antlr, which makes it even harder to find what’s wrong (Weblogic just shuts down). The correct solution is to set the Hibernate property “hibernate.query.factory_class” to “org.hibernate.hql.classic.ClassicQueryTranslatorFactory” (in your Spring configuration or in hibernate.properties).
See also this post about a Hibernate antlr patch.