【问题标题】:HibernateDaoSupport , transaction is not rolled backHibernateDaoSupport ,事务不回滚
【发布时间】:2011-01-28 17:42:59
【问题描述】:

我正在使用 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 会使用/创建一个新会话..

【问题讨论】:

    标签: java hibernate spring


    【解决方案1】:

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

    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 参考文档中关于事务管理和 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 代码组合在同一个应用程序中。)

    【讨论】:

    • 后面的部分已经解决了。我想进入 AOP 或基于注释的事务之前了解这一点。
    • b) 是我目前能想到的唯一罪魁祸首。 IE。发生了一些神奇的事情。最后,我跳过了整个部分,并提出了基于 AOP 注释的事务管理的建议,摆脱了 HibernateDaoSupport 并直接在 DAO 中注入了 LocalSessionFactoryBean。工作正常。
    【解决方案2】:

    如果您看到 HibernateDaoSupport.getSession() 的 JavaDoc,它说它将获得一个新会话或为您提​​供现有事务使用的会话。在您的情况下,HibernateDaoSupport 中还没有列出交易。

    所以如果你使用 getHibernateTemplate().getSession() 而不是 getSession(),你应该得到 HibernateTemplate 使用的会话,然后上面的方法就可以工作了。

    请告诉我进展如何。

    编辑:

    我同意它受到保护……我的错。因此,另一个选择是保持会话线程绑定,这通常是 Web 应用程序中的最佳实践。如果 HibernateDaoSupport 要查找线程绑定会话,则它不会创建新会话并使用相同的会话。这应该可以让你回滚。

    【讨论】:

    • 您可能找到了原因,尽管 getSession() 在 HibernateTemplet 中受到保护,所以我无法控制该会话。
    • @Anonym,尝试为 org.springframework 和 org.hibernate 类别启用调试日志记录,以了解幕后发生的事情。
    猜你喜欢
    • 2011-09-19
    • 2012-07-13
    • 2013-12-15
    • 2011-01-26
    • 2017-03-03
    • 2012-03-10
    • 1970-01-01
    • 2018-07-15
    相关资源
    最近更新 更多