准备这几天如果有空整理一下,先放在这里。
要正确理解OpenSessionInView必须具备以下几个知识点:
1.
servlet的多线程模型。
2.
Filter的工作原理。
3.
ThreadLocal的使用。
4.
Hibernate的Session以及Connection的管理。
5.
Lazy Load
6.
Hibernate的FlushMode
7.
Spring的处理分两种:
7.1 One session per request
7.2 One new session per operation(这里的operation是指一次业务操作,例如如果我们的一次请求调用了某个业务方法,而这个方法里面有两个与Session相关的操作,则每一个操作都会新开一个Session,但是使用结束以后并不关闭,而是注册到ThreadLocal的deffered close 的变量里面,等到open session in view filter执行完毕的最后进行一起close, 这样有个问题就是一个request可能会启动很多Session,而且这些session之间的一级缓存不能共享,另外Hibernate限制不能在一个session里面load一个po却在这个session没有关闭的情况下面在另外一个session里面save或者update,也就是说同一个po实例同一时间只能跟一个session发生关联,这样导致的结果是如果在上面假设的两个业务方法中的第一个进行load,而在第二个中对load出来的进行修改,铁定会报错。)
另外如果是One session per request (官方说法是叫SingleSession Mode), 会看到在open session in view filter中进行了FlushMode.setMode(Never),也就是从来不进行flush, 想当然地就是只能进行read-only的操作。但是没有关系,回到HibernateTemplate的模板方法以及SessionFactoryUtil的getSession方法,可以看到我们的业务方法发出的每个请求都会试图先取到一个session(取session的策略与上面描述的有关),在取Session的过程中会判断当前的操作是不是配制成read-only的(同时也会注册transaction sync manager,有spring和Jta两种),如果不是read-only并且当前的flush mode 是 never的话,会把flush mode改成auto,因此就可以进行读写操作了。
spring的callback使得所有的操作最后基本归由HibernateTemplate当中的excute方法进行处理,对session的管控也是在这里集中进行,如果我们自己控制session,有两种方法,一种是我们也写callback,让spring帮我们擦屁股,另外一种是直接调用HibernateTemplate的getSession方法,但是需要我们对session的生命周期以及关闭作仔细的控制,具体的控制策略可以参考spring地实现。