谨慎使用OpenSessionInViewFilter

用了OpenSessionInViewFilter之后,程序开发确实少了很多问题。一个直接的优点就是,不用再去关心lazy-loading的问题,因为在一个Request的处理周期内,Session都是Open的。

但是,"Great Charge means great responsibility",更大的方便也就意味着更大的责任。此Filter运用时也要非常小心。

从OpenSessionInViewFilter的文档中,我们可以看到下面一段话:


/*Quote */

WARNING: Applying this filter to existing logic can cause issues that
have not appeared before, through the use of a single Hibernate Session for the
processing of an entire request. In particular, the reassociation of persistent
objects with a Hibernate Session has to occur at the very beginning of request
processing, to avoid clashes with already loaded instances of the same objects.


Alternatively, turn this filter into deferred close mode, by specifying
"singleSession"="false"
: It will not use a single session per request then,
but rather let each data access operation or transaction use its own session
(like without Open Session in View). Each of those sessions will be registered
for deferred close, though, actually processed at request completion.

A single session per request allows for most efficient first-level caching,
but can cause side effects
, for example on saveOrUpdate or if continuing
after a rolled-back transaction
. The deferred close strategy is as safe as
no Open Session in View in that respect, while still allowing for lazy loading
in views (but not providing a first-level cache for the entire request).

Looks up the SessionFactory in Spring's root web application context.
Supports a "sessionFactoryBeanName" filter init-param in web.xml;
the default bean name is "sessionFactory". Looks up the SessionFactory on each
request, to avoid initialization order issues (when using ContextLoaderServlet,
the root application context will get initialized
after this filter).

NOTE: This filter will by default not flush the Hibernate Session,
as it assumes to be used in combination with service layer transactions that care
for the flushing, or HibernateAccessors with flushMode FLUSH_EAGER. If you want this
filter to flush after completed request processing, override closeSession
and invoke flush on the Session before closing it. Additionally, you will
also need to override getSession() to return a Session in a flush mode
other than the default FlushMode.NEVER. Note that getSession
and closeSession will just be invoked in single session mode!

在Hibernate的论坛里面,我也看到了类似的话,

// Quote


An alternative solution that you don't need to implement yourself is to use the Spring Franmework's OpenSessionInViewFilter class. You simply define a servlet filter mapping for the filter and it takes care of opening a Session when a request comes in and closing it when the response is generated.

In fact, it will even bind the Session to the current thread and Spring provides a static SessionFactoryUtils.getSession() method that intelligently returns the bound Session or a new one (optionally).

We use this pattern in our Struts application and it works like a charm. You can reliably get the one Session even if you use jsp:include and you can pass around your Hibernate POJOs without worrying about lazy initialization exceptions anywhere.

However, be aware that having a single Session open for an entire request/response cycle can result in some unexpected behavior that did not happen before. We encountered this ourselves, but dealt with it by using the JUnit setUp() and tearDown() methods to mimic the OpenSessionInViewFilter behavior in our unit tests and solving the quirks from there.


Single Session虽然可以最大限度的使用Session中的一级缓存,然而,却可能带来很多的副作用。 我在项目中也碰到了这样的问题(saveOrUpdate之后的查询仍旧返回保存前的值)

/**Quote From Pro Hibernate 3*/


Caution The analogy between a Hibernate Session and a JDBC connection only goes so far. One important difference is that if a Hibernate Session throws an exception of any sort, you should discard it and obtain a new one. This prevents data in the session’s cache from becoming inconsistent with the database.


 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值