ApplicationException - Java - Hibernate - 回滚相关

时间:2010-01-08 17:37:39

标签: java hibernate orm jpa jta

我的问题与交易和例外有关

要求:

我有10条记录要插入到数据库表中。插入每条记录后,我将数据插入另一个表中。因此,如果插入第二个表失败,我想回滚该记录。

实施例。 说一次处理10人的现金转账(从一个账户到账户)。

伪代码: ------------- EJB方法的开始

for(int i = 0; i < TransferRecords.length; i++)
{
    try
    {
          //Deduct cash from TransferRecord.accountFrom --- Includes use of Hibernate Session
          //Add cash in TransferRecord.accountTo -- Includes use of Hibernate Session
     } catch(AppException exception)
     {
            //Rollback the transaction only for this particular transfer (i)
            // But here when I go for next record it says session is closed
     }
}

--------- EJB方法结束

这里使用@ApplicaitonException(rollback = true)annotion创建了AppException。

我们想要的功能是:即使TransferRecord的事务失败(比如说2),我希望为记录0,记录1,记录3,记录4(等等......)提交数据,但不是用于记录2)

但问题是:当TransferRecord 2失败时,当我转移到TransferRecord 3时,我收到“Session Closed”错误。

我的怀疑是: 这是正确的做法吗?或者我应该在EJB之外运行for循环(对于每个TransferRecord) 2.如何确保会话未关闭但事务已回滚(仅针对特定失败事务的事务)

提前谢谢。

我使用的是EJB3,Hibernate 3.x,Jboss 4.2.x,我正在使用容器管理事务。

3 个答案:

答案 0 :(得分:2)

  

这是一种正确的方法吗?

不,使用CMT,您的方法是您的交易单位。所以这里,你所有TransferRecord并在同一个唯一的交易中处理。

顺便问一下,你如何回滚交易?您传播RuntimeException还是致电setRollbackOnly()?我只是好奇。

  

或者我应该在EJB之外运行for循环(对于每个TransferRecord)?

为什么在外面?没有什么能迫使你这样做。如果要在自己的事务中处理每个TransferRecord,则应将它们传递给另一个 EJB方法(下面的代码受this answer启发):

// supposing processRecords is defined on MyStatelessRemote1 and process defined on MyStatelessLocal1
@Stateless
@TransationAttribute(TransactionAttributeType.NOT_SUPPORTED)
public class MyStatelessBean1 implements MyStatelessLocal1, MyStatelessRemote1 {
    @EJB
    private MyStatelessLocal1 myBean;

    public void processRecords(List<TransferRecord> objs) {
        // No transactional stuff so no need for a transaction here
        for(Object obj : objs) {
            this.myBean.process(obj);
        }
    }

    @TransationAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void process(TransferRecord transferRecord) {
        // Transactional stuff performed in its own transaction
        // ...
    }
}
  

如何确保会话未关闭但事务已回滚(仅针对特定失败事务的事务)

我想我已经涵盖了这一部分。

答案 1 :(得分:1)

你在这里唯一的选择是使用用户事务而不是bean之外的循环容器管理事务,这样每次进入bean时你都会得到带有相关事务和连接的新实体管理器(基本上是会话)

答案 2 :(得分:0)

我认为您可以创建两个独立的事务,第一个用于TransferRecord(1)(一旦一切正常就执行提交),然后为所有TransferRecord(i + 1)启动其他TX。

另一种方法是使用保存点,能够回滚并丢弃通过该保存点的所有内容(但我更喜欢第一种方法)。

问候。