Session instance and its persistent instances are used for the whole conversation, known as session-per-conversation. Hibernate checks instance versions at flush time, throwing an exception if concurrent modification is detected. It's up to the developer to catch and handle this exception (common options are the opportunity for the user to merge changes or to restart the business conversation with non-stale data).
Session is disconnected from any underlying JDBC connection when waiting for user interaction. This approach is the most efficient in terms of database access. The application need not concern itself with version checking or with reattaching detached instances, nor does it have to reload instances in every database transaction.
// foo is an instance loaded earlier by the old session
Transaction t = session.beginTransaction(); // Obtain a new JDBC connection, start transaction
session.flush(); // Only for last transaction in conversation
t.commit(); // Also return JDBC connection
session.close(); // Only for last transaction in conversation
foo object still knows which
Session it was loaded in. Beginning a new database transaction on an old session obtains a new connection and resumes the session. Committing a database transaction disconnects a session from the JDBC connection and returns the connection to the pool. After reconnection, to force a version check on data you aren't updating, you may call
LockMode.READ on any objects that might have been updated by another transaction. You don't need to lock any data that you are updating. Usually you would set
FlushMode.NEVER on an extended
Session, so that only the last database transaction cycle is allowed to actually persist all modifications made in this conversation. Hence, only this last database transaction would include the
flush() operation, and then also
close() the session to end the conversation.
This pattern is problematic if the
Session is too big to be stored during user think time, e.g. an
HttpSession should be kept as small as possible. As the
Session is also the (mandatory) first-level cache and contains all loaded objects, we can probably use this strategy only for a few request/response cycles. You should use a
Session only for a single conversation, as it will soon also have stale data.
(Note that earlier Hibernate versions required explicit disconnection and reconnection of a
Session. These methods are deprecated, as beginning and ending a transaction has the same effect.)
Also note that you should keep the disconnected
Session close to the persistence layer. In other words, use an EJB stateful session bean to hold the
Session in a three-tier environment, and don't transfer it to the web layer (or even serialize it to a separate tier) to store it in the
The extended session pattern, or session-per-conversation, is more difficult to implement with automatic current session context management. You need to supply your own implementation of the
CurrentSessionContext for this, see the Hibernate Wiki for examples.