【问题标题】:JtaTransactionManager EntityInterceptor Prototype Spring/HibernateJtaTransactionManager EntityInterceptor 原型 Spring/Hibernate
【发布时间】:2017-06-22 12:57:39
【问题描述】:

我们将应用程序从 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(我们实际使用的)中设置它。
有什么理由,为什么这些事务管理器的功能不同? 有没有其他方法可以使用这样的实体拦截器?

【问题讨论】:

    标签: spring hibernate jta


    【解决方案1】:

    我们找到了两种解决方法。
    其中之一是在 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>
    

    自己的会话上下文:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-08
      • 1970-01-01
      • 2016-07-01
      • 1970-01-01
      • 2013-01-13
      相关资源
      最近更新 更多