2013-05-22 221 views
1

中使用Hibernate JPA和Spring @Transactional(与Atomikos公司JTA实现)我在我的系统下面的实体:春天JPA @Transactional原子

  • 订购
  • 订单行(持有参考排序)
  • 客户

在具有@Transactional欲执行以下步骤注解服务类方法addOrder,在一个transacti (这是一个原子功能块)。

  1. 坚持订单
  2. 坚持的Orderlines
  3. 保留客户

在步骤1(持续次序)我想JPA回滚任何Exception

在步骤2(坚持Orderlines)我想在持续订单行期间忽略任何错误。所以如果我有10个命令行并且1个因任何原因失败(例如违反约束),我想继续处理其他命令。

在步骤3在任何Exception我想JPA回滚整个事务,因此也已在步骤1和2

我遇到了问题所做的一切的情况下,到目前为止:

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

这是最好的方法是什么?

更新

我应该把所有的验证Java和人工检查的记录已经存在,例如?

回答

1

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

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

@Bhasit在这种情况下我遇到上述问题2。违反约束(例如实体已存在)可能只有在完成提交时才会被注意到。此提交仅在主服务结束时完成,因为这是交易的结束。 –

+0

你想忽略condtraint违规?另外,您正在使用哪个交易管理器? –

+0

基本上我想能够忽略由持久化Orderline引起的任何(运行时)异常。我们正在使用Atomikos。 –

0

在步骤2(持续的Orderlines)我想要一个订单项目的持续存在的过程中忽略任何错误 。所以,如果我有10个orderlines和 1由于某种原因失败(违反约束例如)我想 继续与其他人。

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

但在这种情况下,你应该创建一个使用REQUIRES_NEW折返方法,表明坚持每个订单行一个新的事务:

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

因为故障持续的订单项目不应在另一影响,必须创建一个新的事务为每一个。因此,放弃TransactionA-OrderLineA不会影响TransactionB-OrderlineB。

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

也许你应该检讨这些需求。

+0

用这个设置我得到了第3步的问题。如果出现任何问题,我需要回滚。但由于命令行已经在单独的事务中提交(因为Propagation.REQUIRES_NEW),所以我无法回滚这些命令行。除此之外,Orderline还提到订单,该订单属于未交付的交易。所以我会得到一个参照完整性约束违规我相信。 –

0

是必要的顺序?第2步能成为第3步吗?

如果是这样,将步骤1 & 3放入一个单独的事务中,并将每个单独的persist Orderline放入它自己的事务中,以后再运行。当然,如果你需要回滚如果所有 Orderlines不坚持这是不行的......

另一种方法可能是与你的Orderline实体的工作创造一个非托管 EntityManager的;启动事务,捕获异常,并自行管理提交/回滚。

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

“原子性”在实践中往往是相对的野兽 - 很大程度上取决于你的“交易隔离”的强度和选择的“锁定水平”(乐观或悲观w /变化)。我最初的想法是,如果你像线程同步问题那样处理这个问题,并且保持嵌套顺序的一致性('outer'总是处理X,而'inner'总是处理'Y' ) - 你应该是可以的,因为串行顺序在其中应用的变化将保持一致。

+0

你的第一种方法可以在这种特殊情况下工作。但是我可以想像我有另一组我想要坚持的实体,并忽略它的例外。然后我会再次遇到同样的问题。关于另一种方法,那将是一个完全不同的事务,所以它会打破我的原子性,不是吗? –

+0

查看我的想法更新 –

+0

如果您忽略某些实体的异常,它仍然是事务性的吗?这会导致ACID的C失败。我想知道这个解决方案可以用于保存点,但是,JPA并没有很好地发挥。 – Luciano