`

HibernateInterceptor

    博客分类:
  • Java
 
阅读更多

不能用OpenSessionInView的情况,例如在quartz的job中需要保持hibernate的session

 

参考一下链接

 

http://forum.springsource.org/showthread.php?71337-OSIV-in-a-non-web-application

 

 

Our system is divided into two major "application" and "kernel" layers. Each layer hosts of a number of different services & components all deployed and wired together via spring. The kernel layer defines mechanism and the application layer defines policy. There is also a web-layer which calls into applications & kernel components to do configuration, monitoring..etc. At the moment, everything is running in-process.

To promote loose coupling, we generate ApplicationEvent(s) within the kernel layer which are processed asynchronously (on different thread pool threads) up in the application layer by whoever cares about them. The event handlers often call back down into kernel services which do use @Transactional but with no outer session available, I had LIE problems. At the same time, I did not want the application level event handlers to define an outer transaction scope and I also didn't want to put REQUIRES_NEW on all service methods in the kernel layer.

This is how the system is structured and this problem has nothing do with web interfaces or views. I wanted OSIV functionality inside the application event handlers. There are valid arguments against OSIV but I personally feel OSIV is necessary to get the full productivity benefit(s) of using an ORM in the first place.

First, I tried annotating the event handler with 
@Transactional(propagation=Propagation.NEVER) but that didn't work. The transaction manager still didn't bind a hibernate session for me. I'm not sure why but I didn't really look into it.

My solution also uses the HibernateInterceptor. I defined the interceptor and configured it with the same settings as the OSIV filter.


Code:
<bean id="hibernateSessionAdvice" class="org.springframework.orm.hibernate3.HibernateInterceptor">
	<property name="sessionFactory"><ref local="sessionFactory"/></property>
	 <property name="flushModeName" value="FLUSH_NEVER"/>
	 <property name="exceptionConversionEnabled" value="false"/>
</bean>
Then I created a marker annotation I can stick on any method where I want the hibernate interceptor to run.

Code:
package com.tvrc.as.support.spring;

public @interface HibernateSession {

}
I added an aop:config entry to tie the advice to any methods marked with the annotation.

Code:
 <aop:config>
   <aop:advisor pointcut="@annotation(com.tvrc.as.support.spring.HibernateSession)" advice-ref="hibernateSessionAdvice"/>
 </aop:config>
Finally, I just annotate event handlers where I'd like OSIV functionality.

Code:
@HibernateSession
public void onApplicationEvent(ApplicationEvent arg0) {
		//Call kernel services that define transactions
              //Session is available to avoid LIE
}
Spring is creating the application event listeners and wiring them all up so everything works well.
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics