Understand The Problem
If you access detached objects that have been loaded in the Session inside your JSP (or any other view rendering mechanism), you might hit an unloaded collection or a proxy that isn't initialized. The exception you get is: LazyInitializationException: Session has been closed (or a very similar message). Of course, this is to be expected, after all you already ended your unit of work.A
LazyInitializationException
will be thrown by Hibernate if an uninitialized collection or proxy is accessed outside of the scope of the Session
, i.e., when the entity owning the collection or having the reference to the proxy is in the detached state. Solution One
Hibernate.initialize()
Hibernate.isInitialized()
The static methods
Hibernate.initialize()
and Hibernate.isInitialized()
, provide the application with a convenient way of working with lazily initialized collections or proxies. Hibernate.initialize(cat)
will force the initialization of a proxy, cat
, as long as its Session
is still open. Hibernate.initialize( cat.getKittens() )
has a similar effect for the collection of kittens. Solution Two
Another option is to keep the
Session
open until all required collections and proxies have been loaded. In some application architectures, particularly where the code that accesses data using Hibernate, and the code that uses it are in different application layers or different physical processes, it can be a problem to ensure that the
Session
is open when a collection is initialized.There are two basic ways to deal with this issue:
- In a web-based application, a servlet filter can be used to close the
Session
only at the end of a user request, once the rendering of the view is complete (the Open Session in View pattern). - In an application with a separate business tier, the business logic must "prepare" all collections that the web tier needs before returning. This means that the business tier should load all the data and return all the data already initialized to the presentation/web tier that is required for a particular use case. Usually, the application calls
Hibernate.initialize()
for each collection that will be needed in the web tier (this call must occur before the session is closed) or retrieves the collection eagerly using a Hibernate query with aFETCH
clause or aFetchMode.JOIN
inCriteria
. This is usually easier if you adopt the Command pattern instead of a Session Facade. - You can also attach a previously loaded object to a new
Session
withmerge()
orlock()
before accessing uninitialized collections or other proxies. Hibernate does not, and certainly should not, do this automatically since it would introduce impromptu transaction semantics.
http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/performance.html#performance-fetching-initialization
No comments:
Post a Comment