HibernateDaoSupport,事务没有回滚

Ano*_*nym 5 java spring hibernate

我正在使用Spring + Hibernate和PostgreSQL的一些"手动"事务管理我想尝试这一点,并在转向基于aop的事务管理之前理解它是如何工作的.

@Repository
public class UserDAOImpl extends HibernateDaoSupport implements UserDAO {

    @Override
    public void saveUser(User u) {
        Transaction tx = getSession().beginTransaction();
        getHibernateTemplate().saveOrUpdate(u);
        tx.rollback();

    }
}
Run Code Online (Sandbox Code Playgroud)

在这里调用saveUser,我假设保存一个新用户将被回滚.但是,移动到psql命令行后,用户将保存在表中.

为什么不回滚,我需要配置什么以这种方式进行交易?

编辑; 多一点调试似乎表明getHibernateTemplate()使用的不同于getSession()返回的会话(?)

将代码更改为

Transaction tx = getSession().beginTransaction();
getSession().persist(u);
tx.rollback();
Run Code Online (Sandbox Code Playgroud)

并且事务确实被回滚.但我仍然不明白为什么hibernateTemplate会使用/创建一个新会话.

Bob*_*obG 2

我想到了几种可能性(没有双关语):

a) 您的 JDBC 驱动程序默认为 autocommit=true 并且以某种方式忽略 beginTransaction() 和 rollback() 调用;

b) 如果您使用 Spring 3,我相信SessionFactory.getSession() 返回由 Spring 代理包装的 Hibernate Session 对象。Spring代理在Session上设置的部分目的是处理事务管理,也许它可能会干扰您的手动事务调用?

虽然您当然可以使用 AOP 范围的代理进行事务管理,但为什么不在服务层方法上使用 @Transactional(readOnly=false|true) 注释呢?在服务层方法的 Spring 配置文件中,您需要做的就是添加

<tx:annotation-driven />
Run Code Online (Sandbox Code Playgroud)

分别参见 Spring 参考文档中有关事务管理和 ORM 数据访问的第 10 章和第 13 章:

http://static.springsource.org/spring/docs/3.0.x/reference/index.html

最后,如果您使用 Spring 3,则可以通过将 Spring 代理的 SessionFactory bean 注入到 DAO 代码中来消除代码中对 Spring 框架的引用 - 不再需要使用 HibernateDaoSupport。只需注入 SessionFactory,获取当前 Session,然后根据 Hibernate 示例使用 Hibernate 即可。(如果需要,您可以在同一个应用程序中组合 HibernateDaoSupport 和基于 SessionFactory 的普通 Hibernate 代码。)