JtaTransactionManager EntityInterceptor 原型 Spring/Hibernate
JtaTransactionManager EntityInterceptor Prototype Spring/Hibernate
我们将应用程序从 Spring 3.2.13.RELEASE/Hibernate 3.5.6-Final 升级到 Spring 4.3.6.RELEASE/Hibernate 4.2.20.Final-红帽-1。
在 Hibernate 3 中,我们有 HibernateInterceptor,它有一个很好的功能。
我们使用这个拦截器通过打开一个新会话来设置我们的 EntityInterceptor(Prototype)。
<bean id="hibernateInterceptor" class="org.springframework.orm.hibernate3.HibernateInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
<property name="entityInterceptorBeanName">
<value>entityInterceptorName</value> <!--set with BeanFactory -->
</property>
</bean>
<bean id="entityInterceptorName" class="..." scope="prototype" />
Spring/Hibernate 4 中没有任何等效项 class。
我们知道,HibernateTransactionManager 具有类似的功能,但无法在 JtaTransactionManager(我们实际使用的)中设置它。
有什么原因,为什么这些事务管理器的功能不同?
还有其他方法可以像那样使用实体拦截器吗?
我们找到了两个解决方法。
其中之一是在 SessionFactory 上用我们的 Class 定义 hibernate.current_session_context_class。我们的 class 设置了 JTASessionContext 的实现。
<property name="hibernateProperties">
<props>
*
<prop key="hibernate.current_session_context_class">org.path.to.my.context.MySpringSessionContext</prop>
*
</props>
</property>
自己的会话上下文:
public class MySpringSessionContext extends SpringSessionContext {
public MySpringSessionContext(SessionFactoryImplementor sessionFactory) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
super(sessionFactory);
Field transactionManager = this.getClass().getSuperclass().getDeclaredField("transactionManager");
transactionManager.setAccessible(true);
Object value = transactionManager.get(this);
if (value != null) {
Field jtaSessionContext = this.getClass().getSuperclass().getDeclaredField("jtaSessionContext");
jtaSessionContext.setAccessible(true);
jtaSessionContext.set(this, new MySpringJtaSessionContext(sessionFactory));
}
}
}
自己的 JTASessionContext:
public class MySpringJtaSessionContext extends SpringJtaSessionContext {
private BeanFactory beanFactory;
private String entityInterceptor;
public MySpringJtaSessionContext(SessionFactoryImplementor factory) {
super(factory);
//Ugly but we need Spring
Interceptor interceptor = factory.getInterceptor();
if(interceptor instanceof MyBeanFactoryInterceptor){
this.beanFactory = ((MyBeanFactoryInterceptor) interceptor).getBeanFactory();
this.entityInterceptor = ((MyBeanFactoryInterceptor) interceptor).getEntityInterceptorBeanName();
}
}
@Override
protected SessionBuilder baseSessionBuilder() {
return super.baseSessionBuilder().interceptor(getEntityInterceptor());
}
public Interceptor getEntityInterceptor() throws IllegalStateException, BeansException {
if (this.beanFactory == null) {
return EmptyInterceptor.INSTANCE;
}
return this.beanFactory.getBean((String) this.entityInterceptor, Interceptor.class);
}
}
其他解决方法:使用 OpenSessionInterceptor(覆盖),但还有一些其他困难。(刷新,关闭会话)但是像:
使用实体拦截器打开会话:
@Override
protected Session openSession() {
try {
Session session = getSessionFactory().withOptions().interceptor(getEntityInterceptor()).openSession();
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
session.setFlushMode(FlushMode.MANUAL);
} else {
session.setFlushMode(FlushMode.AUTO);
}
return session;
} catch (HibernateException ex) {
throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
}
}
从Spring获取拦截器:
public Interceptor getEntityInterceptor() throws IllegalStateException, BeansException {
if (this.entityInterceptor instanceof String) {
if (this.beanFactory == null) {
throw new IllegalStateException("Cannot get entity interceptor via bean name if no bean factory set");
}
return this.beanFactory.getBean((String) this.entityInterceptor, Interceptor.class);
}
return (Interceptor) this.entityInterceptor;
}
我们将应用程序从 Spring 3.2.13.RELEASE/Hibernate 3.5.6-Final 升级到 Spring 4.3.6.RELEASE/Hibernate 4.2.20.Final-红帽-1。
在 Hibernate 3 中,我们有 HibernateInterceptor,它有一个很好的功能。
我们使用这个拦截器通过打开一个新会话来设置我们的 EntityInterceptor(Prototype)。
<bean id="hibernateInterceptor" class="org.springframework.orm.hibernate3.HibernateInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
<property name="entityInterceptorBeanName">
<value>entityInterceptorName</value> <!--set with BeanFactory -->
</property>
</bean>
<bean id="entityInterceptorName" class="..." scope="prototype" />
Spring/Hibernate 4 中没有任何等效项 class。
我们知道,HibernateTransactionManager 具有类似的功能,但无法在 JtaTransactionManager(我们实际使用的)中设置它。
有什么原因,为什么这些事务管理器的功能不同?
还有其他方法可以像那样使用实体拦截器吗?
我们找到了两个解决方法。
其中之一是在 SessionFactory 上用我们的 Class 定义 hibernate.current_session_context_class。我们的 class 设置了 JTASessionContext 的实现。
<property name="hibernateProperties">
<props>
*
<prop key="hibernate.current_session_context_class">org.path.to.my.context.MySpringSessionContext</prop>
*
</props>
</property>
自己的会话上下文:
public class MySpringSessionContext extends SpringSessionContext {
public MySpringSessionContext(SessionFactoryImplementor sessionFactory) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
super(sessionFactory);
Field transactionManager = this.getClass().getSuperclass().getDeclaredField("transactionManager");
transactionManager.setAccessible(true);
Object value = transactionManager.get(this);
if (value != null) {
Field jtaSessionContext = this.getClass().getSuperclass().getDeclaredField("jtaSessionContext");
jtaSessionContext.setAccessible(true);
jtaSessionContext.set(this, new MySpringJtaSessionContext(sessionFactory));
}
}
}
自己的 JTASessionContext:
public class MySpringJtaSessionContext extends SpringJtaSessionContext {
private BeanFactory beanFactory;
private String entityInterceptor;
public MySpringJtaSessionContext(SessionFactoryImplementor factory) {
super(factory);
//Ugly but we need Spring
Interceptor interceptor = factory.getInterceptor();
if(interceptor instanceof MyBeanFactoryInterceptor){
this.beanFactory = ((MyBeanFactoryInterceptor) interceptor).getBeanFactory();
this.entityInterceptor = ((MyBeanFactoryInterceptor) interceptor).getEntityInterceptorBeanName();
}
}
@Override
protected SessionBuilder baseSessionBuilder() {
return super.baseSessionBuilder().interceptor(getEntityInterceptor());
}
public Interceptor getEntityInterceptor() throws IllegalStateException, BeansException {
if (this.beanFactory == null) {
return EmptyInterceptor.INSTANCE;
}
return this.beanFactory.getBean((String) this.entityInterceptor, Interceptor.class);
}
}
其他解决方法:使用 OpenSessionInterceptor(覆盖),但还有一些其他困难。(刷新,关闭会话)但是像:
使用实体拦截器打开会话:
@Override
protected Session openSession() {
try {
Session session = getSessionFactory().withOptions().interceptor(getEntityInterceptor()).openSession();
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
session.setFlushMode(FlushMode.MANUAL);
} else {
session.setFlushMode(FlushMode.AUTO);
}
return session;
} catch (HibernateException ex) {
throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex);
}
}
从Spring获取拦截器:
public Interceptor getEntityInterceptor() throws IllegalStateException, BeansException {
if (this.entityInterceptor instanceof String) {
if (this.beanFactory == null) {
throw new IllegalStateException("Cannot get entity interceptor via bean name if no bean factory set");
}
return this.beanFactory.getBean((String) this.entityInterceptor, Interceptor.class);
}
return (Interceptor) this.entityInterceptor;
}