Don't Let Hibernate Steal Your Identity
Subject:   Thanks
Date:   2007-01-14 14:10:15
From:   jbrundege
Response to: Thanks

Thanks rakeshpatel1 for pointing this out. Yes, they didn't like this article at all. We've had a quite a discussion over the past week which you can read from the above link.

Here's a quick summary:
Their criticism was that I launched into a discussion of object identity with the assumption that you had to override equals() and hashCode(). Their position is that you only have to override these methods if you use detached objects. And they feel there are much better alternatives to using detached objects. This is fair. When I've used application-assigned UUIDs I've also used detached objects, which I didn't even point out much less mention the alternatives.

The alternatives basically involve keeping the Hibernate Session around in between transactions. Since the Session holds a map of persisted objects, if you never discard the Session you're always guarenteed to return the same instance of an object each time you request it. You can then use the default implementation of equals() and hashCode() since you won't load two separate instances of the same object. You can still use application-assigned ids on your objects and override these methods if you want to, but a key motivation for doing so is gone.

There are several ways to avoid discarding the Session between requests. If you have a two-tiered application (ui layer, service layer, and data access layers are all replicated on each of your web servers while the database may be on another machine), you can put the Hibernate Session on the HttpSession. This can be done with an interceptor or servlet filter that works before the rest of your ui, so you donít contaminate your ui or service layer with any persistence code. The interceptor can then call the Hibernate method ManagedSessionContext.bind(session), which binds the Session to a ThreadLocal map of Sessions where it can be picked up again and used by your Data Access Object. In this way something at the front of your application (ui interceptor or servlet filter) can manage the creation and storage of a Session for each user conversation, and the DAO at the back of the application can use it without having to explicitly pass it through all the intervening application layers (which shouldn't have to know what persistence framework you're using).

If you have a stateless layer between the web server and the DAO (such as a 3-tier architecture using stateless session EJBs) this won't work. That is, if the DAO is on a different machine than the web server it won't have access to a ThreadLocal bound Hibernate Session. In that case you can't store the Hibernate Sessions in the HttpSession, and will have to store them in the service layer. One way to do this is with Stateful Session EJBs.

The terminology has shifted around a bit, so just to clarify: older documentation on this refers to it as "long session", newer documentation as "extended session". There's also many references to it as the "session-per-conversation" strategy to highlight the idea of scoping the Session to a conversation between the user and the app which involves multiple request/response cycles. With the EJB 3.0 spec and the Java Persistence API the relevant interface is named EntityManager instead of Session, so the terminology sometimes shifts to the more generic "extended persistence context". In this case the "persistence context" could be a Session or EntityManager.

Here's some links to the relevant documentation:

The best descriptions are in the books:
Hibernate in Action: Section 8.2.4: Using a long session
Java Persistence with Hibernate: Section 11.2.3: Extending a Session for a conversation

Sparce description in the Reference Documentation:

Related sections in the JPA EntityManager documentation:

Section in the wiki on the open session in view pattern:

1 to 1 of 1
1 to 1 of 1