使用TransageProxyFactoryBean与Spring和Hibernate

2022-09-04 04:34:20

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

我们使用这种方法来配置我们的交易。

也就是说,在 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 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级别,并遇到了同样的问题。

如果这对于堆栈溢出格式来说太详细了,请道歉。


答案 1
  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. 添加休眠事务管理器

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

    <tx:annotation-driven transaction-manager="transactionManager"/>
    
  5. 确保用于创建会话工厂LocalSessionFactoryBean

以下是配置 Spring 和 Hibernate 4 的详细分步教程


答案 2

推荐