JtaTransactionManager EntityInterceptor Prototype Spring / Hibernate

时间:2017-06-22 12:57:39

标签: spring hibernate jta

我们将我们的应用程序从Spring 3.2.13.RELEASE / Hibernate 3.5.6-Final升级到Spring 4.3.6.RELEASE / Hibernate 4.2.20.Final-redhat-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中没有任何等效类。
我们知道,HibernateTransactionManager具有这样的功能,但是没有办法在JtaTransactionManager中设置它(我们实际使用的是什么)。
有什么理由,为什么这些Transactionmanagers功能不同? 有没有其他方法可以像这样使用Entityinterceptor?

1 个答案:

答案 0 :(得分:0)

我们找到了两个解决方法。
其中之一是使用SessionFactory上的Class定义hibernate.current_session_context_class。我们的类设置了JTASessionContext的实现。

<property name="hibernateProperties">
      <props>
          *
        <prop key="hibernate.current_session_context_class">org.path.to.my.context.MySpringSessionContext</prop>
          *
      </props>
 </property>

拥有sessioncontext:

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(覆盖),但还有其他一些困难。(刷新,关闭会话)但是喜欢:

使用entityinterceptor打开会话:

@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;
}