我已经写了下面的代码做下面的活动我创建使用Spring类一个事务。 插入一行。 创建其他交易。 插入另一行。 提交外部事务。 Rolledback内部事务。
TransactionStatus trxstsOuter= dsTrxMngr.getTransaction(null);
jdbcTemplate.update("insert into kau_emp values(6,'xyz' )");
TransactionStatus trxstsInner= dsTrxMngr.getTransaction(null);
jdbcTemplate.update("insert into kau_emp values(7,'pqr' )");
dsTrxMngr.commit(trxstsOuter);
System.out.println("trxstsOuter.isCompleted()" + trxstsOuter.isCompleted());
System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());
dsTrxMngr.rollback(trxstsInner);
System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());
我观察到,该行致力于DB! 输出是
trxstsOuter.isCompleted()true
trxstsInner.isCompleted()false
trxstsInner.isCompleted()true
它是正确的行为? 不宜内部事务首先被提交/允许外部事务提交之前rollbacked? 如果外部事务被提交,应回滚内引发错误的?
在你的榜样交易Propagation.REQUIRED
作为默认值,所有的逻辑交易被映射到单一物理交易
当传播设置PROPAGATION_REQUIRED,用于在其上施加设定每个方法创建的逻辑事务范围。 每一个这样的逻辑事务范围可以单独仅确定回退状态,其具有外事务范围是从内事务范围逻辑上独立的。 当然,在标准的PROPAGATION_REQUIRED行为的情况下,所有的这些范围将被映射到相同的物理事务。 所以在内部事务范围仅回滚标志设置不影响外部事务的机会真正承诺(如你希望它)。
所以,在你的榜样两个逻辑交易被映射到一个物理事务。
查看文档
在当前的代码的第二getTransaction呼叫是一个空操作。 此行为是由称为PropagationBehavior属性控制。 默认的传播行为PROPAGATION_REQUIRED - 这意味着如果不存在启动新的事务或者加入现有的事务。 而这一点正是你的情况发生。
如果你改变了传播行为属性的第二交易PROPAGATION_REQUIRES_NEW - 你会得到你预期的行为。 外部事务被暂停,并且一旦内部事务被提交创建一个新的事务/回滚外部事务被自动恢复。 我已经修改你的代码将这一行为,那么当您尝试内一个之前提交外部事务,现在得到一个异常。 如果您修复序列,则提交将独立发生。
TransactionStatus trxstsOuter= dsTrxMngr.getTransaction(null);
jdbcTemplate.update("insert into kau_emp values(6,'xyz' )");
// start a new transaction.
DefaultTransactionDefinition nestedTransDef = new DefaultTransactionDefinition();
nestedTransDef.setPropagationBehavior(
TransactionDefinition.PROPAGATION_REQUIRES_NEW);
TransactionStatus trxstsInner= dsTrxMngr.getTransaction(nestedTransDef);
System.out.println("trxstsInner.isNewTransaction()"+ trxstsInner.isNewTransaction());
jdbcTemplate.update("insert into kau_emp values(7,'pqr' )");
dsTrxMngr.commit(trxstsOuter);
System.out.println("trxstsOuter.isCompleted()" + trxstsOuter.isCompleted());
System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());
dsTrxMngr.rollback(trxstsInner);
System.out.println("trxstsInner.isCompleted()" + trxstsInner.isCompleted());
顺便说一句,你应该使用注释管理事务 - 即在你的代码合并交易的更清洁/更好的方式。 程序化交易是只为那些需要更多的控制极少数情况下。 另外,在做使用TransactionTemplate编程事务的建议。