将 TransactionProxyFactoryBean 与 Spring 和 Hibernate 结合使用

Using TransactionProxyFactoryBean with Spring and Hibernate

我有一个旧项目正在尝试升级到 spring 4 / hibernate 4。

我们使用 this 方法来配置我们的事务。

也就是说,在XML中我们定义了一个事务管理器像:

<bean id="abstractTransactionProxy"
abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="hibernateTransactionManager"/>
<property name="transactionAttributes">
    <props>
        <prop key="create*">PROPAGATION_REQUIRED</prop>
        <prop key="update*">PROPAGATION_REQUIRED</prop>
        <prop key="delete*">PROPAGATION_REQUIRED</prop>
        <prop key="*">PROPAGATION_SUPPORTS,readOnly</prop>
    </props>
</property>

<bean id="MySessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource"     ref="myDataSource" />
    <property name="configLocation" value="WEB-INF/hibernate.cfg.xml" />
</bean>

然后我们的每个服务 bean 定义如下:

<bean id="customerService" parent="abstractTransactionProxy">
    <property name="target" ref="customerTarget"/>
    <property name="personDAO" ref="personDAO" />
</bean>

DAO 的定义如下:

    <alias name="personDaoImpl" alias="personDAO"/>
<bean id="personDaoImpl" 
    class="com.foo.bar.hibernate.PersonDaoImpl">
    <property name="sessionFactory" ref="MySessionFactory" />
</bean>

PersonDaoImpl(以及所有其他 DAO)有许多看起来像这样的方法(所有 DAO 都扩展了 HibernateDaoSupport):

    public List<Person> getPersonByCriteria(final String criteria) {
    List<Person> results = 
        (List<Person>) this.getHibernateTemplate().executeFind(new HibernateCallback<List<Person>>(){

        public List<Person> doInHibernate(Session session) throws HibernateException, SQLException {
            List<Person> results = (List<Person>) session.createQuery(MYSQLHERE).setString("criteria", criteria).list();
            return results;
        }
    });
    return results;
}

现在,我现在面临的问题是摆脱我们对从 HibernateDaoSupport 扩展我们的 DAO 的依赖,并通过扩展,摆脱对使用它的 HibernateTemplate 帮助程序对象的依赖。

这是我采取的步骤:

当然这会给我编译时错误,因为 'getSessionFactory' 是我刚刚删除的基础 class 'HibernateDaoSupport' 的一部分。

现在我可以构建、部署和 运行 我遇到了这个错误消息:

No session available in this thread

我怎样才能完成这项工作?

我尝试用@transactional 标记我的 'CustomerService'(调用 'PersonDao' 的业务逻辑对象)但是 (A) 不管怎样我都看到同样的错误并且 (B) 我真的更喜欢能够以编程方式执行此操作,以减少对代码现在工作方式的更改规模。我也尝试将交易放在 DAO 级别,但遇到了同样的问题。

抱歉,对于 Stack overflow 格式来说过于详细了。

  1. 您需要将 SessionFactory 注入您的 DAO 类:

    @Repository
    public class PersonDAOImpl implements PersonDAO {
    
        @Autowired
        private SessionFactory sessionFactory;
    
        public List<Person> getPersonByCriteria(final String criteria) {
            List<Person> results = (List<Person>) getSessionFactory().getCurrentSession().createQuery(MYSQLHERE).setString("criteria", criteria).list();
            return results;
        }
    }
    
  2. @Transactional添加到您的服务方式

  3. 添加HibernateTransactionManager

  4. 指示Spring使用声明式事务:

    <tx:annotation-driven transaction-manager="transactionManager"/>
    
  5. 确保使用 LocalSessionFactoryBean 创建 SessionFactory

这里有详细的步骤tutorial for configuring Spring and Hibernate 4