【问题标题】:JtaTransaction localStatus rolled back after creationJtaTransaction localStatus 创建后回滚
【发布时间】:2014-06-25 14:33:42
【问题描述】:

我正在创建一个休眠 Session 并尝试启动一个新的 [Jta]Transaction。但是,事务无法启动,因为在后台使用的 JtaTransaction 似乎已回滚。

这就是我正在做的事情。

Session session = sessionFactory.openSession();
CustomSessionWrapper dpSession = new CustomSessionWrapper(session, this);

if (!session.isClosed() && !session.getTransaction().isActive()) {
    session.beginTransaction();
}

尽管如此,在调用beginTransaction 之后事务仍然不活动。当我调试beginTransaction方法时,我来到JtaTransactiondoBegin方法(我不重写这个方法,我只是贴出这个方法的原始代码)。

@Override
protected void doBegin() {
    LOG.debug( "begin" );

    userTransaction = locateUserTransaction();

    try {
        if ( userTransaction.getStatus() == Status.STATUS_NO_TRANSACTION ) {
            userTransaction.begin();
            isInitiator = true;
            LOG.debug( "Began a new JTA transaction" );
        }
    }
    catch ( Exception e ) {
        throw new TransactionException( "JTA transaction begin failed", e );
    }
}

userTransaction.getStatus() 返回Status.STATUS_ROLLEDBACK 并且没有事务启动。有谁知道我该如何解决这个问题?

更新 1(您可以跳过,因为这是一个错误,请参阅更新 2)

我发现有两个线程,一个使用主会话,另一个使用较小的会话进行日志记录。主会话(和事务)打开的时间更长,所以基本上直到操作完成。似乎locateUserTransaction 总是返回相同的userTransaction。这意味着主会话打开此 userTransaction 并且其中一个侧事务提交/回滚该事务。有谁知道该怎么做才能检索到不同的交易?

更新 2

我发现我没有两个线程,只有一个线程并行打开两个会话。然后每个会话都应该打开自己的事务,尽管两者都获得相同的 UserTransaction。我如何告诉 hibernate 每个会话都应该有自己的 [User]Transaction?

【问题讨论】:

  • 您是否在应用程序的每个位置都关闭了会话?
  • 是的,当调用CustomSessionWrapper 类的commitrollback 方法时会话总是关闭。

标签: java hibernate jta


【解决方案1】:

Hibernate 在其自己的抽象层后面将两个本地事务抽象为 JTA 事务,所以我不明白您为什么必须编写如此低级的事务处理代码。

在 Java EE 中,您有应用服务器来管理事务,而在独立应用中,Bitronix + Spring 也可以完成工作。

虽然您可以设法编写自己的事务管理逻辑,但我始终建议人们重用他们已有的东西。 Xa/JTA 和 Hibernate 需要广泛的知识才能无缝工作。

更新 1

两个不同的线程不应该使用同一个用户事务,你应该为每个线程使用不同的事务。

【讨论】:

  • 您好,感谢您的建议。可悲的是,我不能使用这种方法有两个原因(尽管如果可以的话我会......)。首先,代码必须适用于 web 服务和胖客户端。 webservices使用jta,而fatclients使用jdbc。其次,这段代码位于一个庞大的代码库中,因此不可能重写所有代码。我们最近从 hibernate 3.2 升级到了 4.3,从那以后就出现了这个问题...
  • 我也没有重写doBegin方法,我只是贴出原始代码,以便告诉你我发现了什么。
  • 我明白了。好吧,如果事务被标记为已回滚,您就不能再使用它了,唯一的解决方案是启动一个新事务。因为事务绑定到线程,你必须让它回滚,退出事务边界并从最近的事务边界开始的外部点重试(通常是@Transactional 服务)。我通常使用 AOP 来执行此操作,如果事务失败但可以恢复(例如乐观锁定、死锁),我只需重试即可。必须调查是什么导致您的事务被回滚。
  • 谢谢,我目前正在处理回滚事务。
  • 我想我找到了回滚事务并更新了问题。也许你知道一些事情:)
猜你喜欢
  • 2021-01-03
  • 2015-08-13
  • 1970-01-01
  • 2022-11-21
  • 1970-01-01
  • 1970-01-01
  • 2020-01-13
  • 2013-09-24
  • 1970-01-01
相关资源
最近更新 更多