Session and Transaction scopeThis document answers the following questions:
- When is the Session opened?
- When is the Session closed?
- What is an "application transaction"?
- What is the granularity of Session, database transaction, and application transaction?
Terminology:
- Session: The Hibernate Session object (first level cache, identity scope)
- Transaction: The Hibernate Transaction object for database transactions
- Application Transaction: A predefined sequence of Request/Response (Http) cycles executed as one unit-of-work
First, don't use the session-per-operation antipattern, that is, don't open and close a Session for every simple database call in a single thread. In a web app without dedicated business layer, use session-per-request: Request comes in, open a new Session, assign it to the thread (ThreadLocal), start a database transaction, assign it to the thread (ThreadLocal). Do some work. Before the Response is send, commit Transaction and close Session. See the Thread Local Session pattern on how to implement the helper class for this. In a layered architecture with transactions demarcated at the business facade level, use session-per-transaction, for example with transactions managed by EJB CMT or Spring (Spring even automatically associates a Hibernate Session with a transaction). As such transactions can seamlessly participate in enclosing ones, gathering multiple business method invocations into one transaction (consequently backed by one single Hibernate Session) is straightforward. See Data Access with the Spring Framework for details on Spring's transaction management. With the Open Session in View pattern on top of a layered architecture, you can use session-per-request-with-multiple-transactions. A web controller might invoke multiple business methods per request, each executing in its own transaction but on the same Hibernate Session, closing the Session after the view has been rendered (to allow for lazy loading). Spring's OpenSessionInViewFilter implements this pattern, without affecting business code. Any of these is perfectly fine for most applications, at least if you don't work with "application transactions". So what is an application transaction? A predefined sequence of (HTTP) request/response cycles is one long application transaction. For example, in a typical dialog: 1. Open new Session and database transaction, read some data, commit and close, show data to the user for modification. 2. User clicks "Save" after 5 minutes, new Session is opened, new database transaction is started, modified objects from 1 have to be saved. We have to perform a version check to ensure nobody modified the objects meanwhile. There are several ways to implement this application transaction: session-per-request-with-detached-objects: Do the same as in session-per-request but use detached objects; instances loaded from a previous Session/Transaction (in 1) are reused in a new Session (in 2). Attach the graph manually in 2, with update() - for an optimistic version check - or lock() - if they have not been modified. session-per-application-transaction: Do the same as in session-per-request but don't close the Session, only disconnect it from the JDBC connection at the end of 1 and reconnect it when the request for 2 comes in. This approach uses a "long Session", but each Request/Respsonse cycle still has only one single database transaction. You dont' have to manually update() or lock(). Always close (or at least clear) the Session after the last Request/Response cycle of the application transaction. In the example above, 1 opens a new Session, after 2, close the Session. Atomicity of the application transaction is only guaranteed if only one Request/Response cylce writes data, all others before just read. Don't use the same Session for multiple application transactions, these antipatterns are called:
- session-per-user-session
- session-per-application
To be continued...
|