HibernateDaoSupport,事务未回滚。

5

我正在尝试使用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();

    }
}

在这里调用saveUser,我想保存一个新用户将被回滚。

然而,移动到psql命令行,用户保存在表中。

为什么不回滚?我需要配置什么才能以这种方式进行事务处理?

编辑:更多的调试似乎表明getHibernateTemplate()使用与getSession()返回的不同的会话(?)

将代码更改为:

Transaction tx = getSession().beginTransaction();
getSession().persist(u);
tx.rollback();

这个事务确实被回滚了。但我仍然不明白为什么hibernateTemplate会使用/创建一个新的session。

2个回答

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 />

请参阅Spring参考文档中的第10章和第13章,分别涉及事务管理和ORM数据访问。

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

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

这个问题的后半部分已经解决了。在深入研究AOP或基于注解的事务之前,我想先弄清楚这个问题。 - Anonym
目前我只能想到 b) 是罪魁祸首。也就是说,有一些神奇的 foo 在发生。最终,我跳过了整个部分,并采用基于 AOP 注释的事务管理建议,摆脱了 HibernateDaoSupport 并直接在 DAO 中注入 LocalSessionFactoryBean。运行良好。 - Anonym

2
如果您查看HibernateDaoSupport.getSession()的JavaDoc,它会说明它将获取一个新的session或者给您现有事务中使用的session。在您的情况下,HibernateDaoSupport中没有列出任何事务。
所以如果您使用getHibernateTemplate().getSession()而不是只使用getSession(),您应该可以获得由HibernateTemplate使用的session,然后上述内容就可以工作了。
请告诉我结果如何。
编辑:
我同意它是受保护的...我的错。那么另一个选择就是保持session与线程绑定,在Web应用程序中通常是最佳实践。如果HibernateDaoSupport将找到线程绑定的session,则不会创建新的session并使用相同的session。这应该让您执行回滚操作。

你可能已经找到了原因,尽管在HibernateTemplet中getSession()是受保护的,所以我无法获取该会话。 - Anonym
@Anonym,请尝试启用org.springframework和org.hibernate类别的调试日志记录,以查看底层发生了什么。 - Binil Thomas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接