在Spring和Hibernate中使用TransactionProxyFactoryBean

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Spring和Hibernate中使用TransactionProxyFactoryBean相关的知识,希望对你有一定的参考价值。

我有一个旧项目,我正在尝试升级到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帮助对象。

这是我采取的步骤:

  • 只需从DAO方法中删除它们 - 不要扩展HibernateDaoSupport,删除HibernateTemplate回调。这看起来像: public List<Person> getPersonByCriteria(final String criteria) { List<Person> results = (List<Person>) getSessionFactory().getCurrentSession().createQuery(MYSQLHERE).setString("criteria", criteria).list(); return results; }

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

  • 所以我实现了一个'MyHibernateDaoSupport'类,并让我的DAO扩展了它。看起来像: public class MyHibernateDaoSupport { private SessionFactory sessionFactory; protected Session session; protected static Logger logger = Logger.getLogger(MyHibernateDaoSupport.class); public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; session = this.sessionFactory.getCurrentSession(); } public SessionFactory getSessionFactory() { return this.sessionFactory; } public Session getHibernateTemplate() { session = this.sessionFactory.getCurrentSession(); return session; } public MyHibernateDaoSupport() { } }

现在我可以构建,部署和运行,并点击此错误消息:

No session available in this thread

我怎样才能做到这一点?

  • 简单来说,'hibernateCallback()'是什么,它的匿名内部类实际上在做什么?
  • 如何在不使用HibernateDaoSupport和HibernateTemplate类的情况下使项目的事务像以前一样工作?

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

如果这对于Stack溢出格式来说太详细了,那就道歉了。

答案
  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

以上是关于在Spring和Hibernate中使用TransactionProxyFactoryBean的主要内容,如果未能解决你的问题,请参考以下文章

Spring Data JPA使用getOne方法报错:Method threw 'org.hibernate.LazyInitializationException' excepti

在Spring中使用Hibernate 4

spring中事务配置

在Spring和Hibernate中使用TransactionProxyFactoryBean

如何在 Spring 和 Hibernate 中使用两个数据库/数据源

使用 Hibernate 和 Spring 创建 Blob