|
From: Juergen H. <ju...@in...> - 2005-05-03 10:20:26
|
James, Yes, this is essentially how Spring's OpenSessionInViewFilter/Interceptor has been working since its inception - in its "single session mode". I'll use the opportunity to discuss this in some detail. OpenSessionInViewFilter/Interceptor will create a Hibernate Session (without a transaction) at the start of request processing and close it after completion of request processing. Each demarcated transaction will take the existing Hibernate Session and begin a transaction on it, flushing and committing at the end of the demarcated transasction. Any number of such transactions can be performed within the same request, on the same Session. In case of a rollback, the Session will receive a clear() call which resets all of its pending updates/deletes. This avoids side effects from dirty state created during the transaction that has just been rolled-back. Any further transactions can still properly load and modify persistent objects and expose them to views, with lazy loading still working. We strongly recommend *against* flushing at request completion. Neither OpenSessionInViewFilter or OpenSessionInViewInterceptor do this, unless you create a custom subclass with an explicit flush call. The recommendation is to only flush at the end of transactions but *never* after view rendering has started. OpenSessionInViewFilter/Interceptor set the Session to FlushMode.NEVER outside transactions, to suppress implicit flushing. For completeness' sake: Aside from transactions, OpenSessionInViewInterceptor also offers the option to flush after controller execution, right before view rendering starts. Spring's HandlerInterceptor gives such a specific callback, but the general Servlet Filter mechanism doesn't, so we cannot provide this for OpenSessionInViewFilter. It's preferable to rely on demarcated transactions instead, in general. ----- As an alternative to the "single session mode" as discussed above, OpenSessionInViewFilter/Interceptor also offers a "deferred close mode" which works quite differently but achieves a similar effect: Each transaction will still open its own Hibernate Session there, but such a Session won't be closed at transaction completion. Instead, each of those Sessions will be kept open until view rendering, to allow for lazy loading. The main disadvantage of the "deferred close mode" is that you cannot associate the same persistent object with two transactions (with both Hibernate Sessions still open): that is, you cannot load a persistent object in one transaction and call "saveOrUpdate" for it in another transaction. What you can do, though, is to store such objects through Hibernate3's "merge": so "deferred close mode" might actually become more viable with Hibernate3. ----- I guess the most important advice (which you're of course already aware of) is: Keep your transactions limited to the business layer or to controller execution - never keep transactions open during view rendering! All changes to persistent objects need to be flushed before view rendering starts: the view should receive independent objects, without the risk of accidental changes getting persisted. Furthermore, database locks need to be released early, *before* starting to render a view: rendering is a potentially intensive I/O operation that might even block in case of congestion. Interestingly, the Hibernate team themselves (and others) tend to ignore this and simply recommend a Servlet Filter that wraps the entire request processing with a JTA transaction, committing *after* view rendering. In particular with Hibernate3's auto-flush and auto-close for JTA transactions, they seem to believe that this is all you need... I guess part of the Hibernate team's argumentation is that you should never do database access outside transactions. As a consequence, lazy loading outside transactions and hence an Open Session in View without transaction is bad. In my opinion, the tradeoff of non-transactional lazy loading is absolutely preferable: it's much more important to flush changes and release database locks before view rendering starts. BTW, TopLink is *very* different in that respect: while it does have a Session concept too, it handles persistent object lifecycle and in particular lazy loading very differently (there is no need for Open Session in View there in the first place, as lazy loading will always work). JDO on the other hand is rather similar to Hibernate, with even stricter lifecycle requirements (Spring ships an OpenPersistenceManagerInViewFilter/Interceptor for JDO too). Juergen -----Original Message----- From: spr...@li... [mailto:spr...@li...]On Behalf Of James Cook Sent: Friday, April 22, 2005 9:54 PM To: spr...@li... Subject: [Springframework-user] Delayed association of transaction with session Jason (from WebWork) has been working up an example demonstrating basic CRUD functionality, and he is using the Open Session In View (OSIV) filter which I have shunned in favor of clearly demarcated transactional boundaries. In his example however, there is a twist that I haven't seen yet. He creates the Hibernate session without a transactional context. Whenever he performs a direct load or update to a persistent object, he creates a transaction, executes the session.save() [or whatever], and commits the transaction. The session is flushed at the end of the transaction. When the view renders it can access any of the objects in the Hibernate session, and use lazy-loaded collections. When the request completes, the OSIV filter does *not* perform a flush. My question is whether Spring automatically works this way? For example: 1. Will the OSIV filter create a Hibernate Session without a transaction starting? 2. When a transactional method is invoked, will a new transaction be created and associated with the already created Hibernate session? 3. When this transactional method completes successfully, will it flush the session and commit the transaction? 4. Can I repeat #2-#3 any number of times against the same session? 5. If the transactional method is not successful and a rollback occurs (for some valid business reason, not a HibernateException), does the Hibernate Session remain accessible and complete? This seems like a decent compromise between OSIV and respect for transactional boundaries for the simplest of applications. There are still gotchas, (lazy-loaded collections executed outside of a transaction, objects in the session that may not reflect the state of the database, dirty objects that are not meant to be persisted, could magically persist themselves on an innocent call from the view to a transaction-bound method), but they could be effectively managed if the app was very simple. ------------------------------------------------------- SF email is sponsored by - The IT Product Guide Read honest & candid reviews on hundreds of IT Products from real users. Discover which products truly live up to the hype. Start reading now. http://ads.osdn.com/?ad_ide95&alloc_id396&op=ick _______________________________________________ Springframework-user mailing list Spr...@li... https://lists.sourceforge.net/lists/listinfo/springframework-user |