Spring JPA @Transactional Atomic

时间:2013-05-22 11:43:44

标签: java spring hibernate jpa spring-transactions

使用Hibernate JPA和Spring @Transactional(使用Atomikos JTA实现)我的系统中有以下实体:

  • 顺序
  • 订单行(保留对订单的引用)
  • 客户

在使用addOrder注释的Service类方法@Transactional中,我希望在一个事务中执行以下步骤(它是一个原子功能块)。

  1. 坚持订单
  2. 坚持订单
  3. 坚持客户
  4. 在第1步(保留订单)我希望JPA在任何Exception上回滚。

    在第2步(保持订单行)我想在订单行的持续存在期间忽略任何错误。因此,如果我有10个订单行,1个因任何原因失败(例如违反约束),我想继续其他的。

    在第3步如果有任何Exception,我希望JPA回滚整个交易,以及在步骤1和2中完成的所有内容。

    到目前为止我遇到的问题:

    • 如果Exception,则JPA将该事务标记为“仅回滚”。所以在此之后(和之前)的所有内容都会回滚,但我想在步骤2中忽略Exception
    • JPA仅在调用flush()commit()后才知道约束违规,这通常是在@Transactional方法完成后。我需要在我的方法中知道它。
    • 尝试在单独的@Transactional方法中拆分每个步骤,但由于他们需要使用相同的Transaction,因此这不会改变前两个问题。

    最佳方法是什么?

    更新

    我是否应该在Java中进行所有验证并手动检查记录是否已存在?

3 个答案:

答案 0 :(得分:1)

将第二部分放在try-catch块中。例如:方法体可能看起来像这样。

save(order);
flush();
for(Orderline line : orderlines) {
    try {
        orderlineService.save(line); 
        flush();   
    } catch(RuntimeException rte) {
        continue;
    }
}
save(customer);

答案 1 :(得分:0)

  

在第2步(保留Orderlines)我想忽略任何错误   在订单持续存在期间。所以,如果我有10个订单行和   1因任何原因失败(例如违反约束)我想   继续与其他人一起。

@Transactional默认是必需的。每个方法invocationg都会加入当前的Transaction,使所有3个操作都成为原子。

但在这种情况下,您应该使用REQUIRES_NEW创建一个可重入的方法,指示用于持久化每个Orderline的新事务:

@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void persistMyOrderLine(OrderLine o) throws Exception{}

因为持续存在订单行的故障不应影响另一个,必须为每个订单创建一个新事务。因此,中止TransactionA-OrderLineA不会对TransactionB-OrderlineB产生影响。

问题:根据您的需要,本质上,操作不再是ATOMIC。因为您有一个忽略失败(订单行)的场景,操作不是ATOMIC,也不会中止角色过程(3个步骤)。

也许您应该检查这些需求。

答案 2 :(得分:0)

订单是否必要?步骤2可以成为第3步吗?

如果是这样,请执行步骤1& 3进入单个事务,并将每个人persist Orderline放入其自己的事务中以便之后运行。当然,如果您需要回滚,如果所有订单行无法继续存在,这将无效...

另一种方法可能是创建一个非托管 EntityManager来处理您的Orderline实体;启动事务,捕获异常,并为您自己管理提交/回滚。

理想情况下,您使用嵌套事务,JPA / JTA doesn't directly support。通过使外部事务的提交/回滚依赖于内部事务成功/失败 - 或忽略(在您的情况下)内部事务,您可以有一些外表。

“原子性”在实践中往往是一个相对的野兽 - 很大程度上取决于你的“交易隔离”的强度,并选择“锁定水平”(乐观或悲观的变化)。

我对此的初步想法是,如果你像线程同步问题那样接近它,并且在嵌套顺序上保持一定的一致性('外部'总是处理X,'内部'总是处理'Y') - 您应该没问题,因为应用更改的序列化订单将保持一致。