我在进行批处理时遇到以下异常
encountered an error.org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only
at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:252)
at java.util.concurrent.FutureTask.get(FutureTask.java:111)
有人可以帮我解决可能存在的问题吗?
感谢。
答案 0 :(得分:6)
你可能在另一个bean中的某个bean中有一个已检查的异常,但是spring的事务通知会注意到它并将标记该事务以进行回滚。
您可以使用Transactional注释的noRollBackFor属性。
答案 1 :(得分:5)
在Spring管理的环境中获得此异常的可能性是事务传播设置为REQUIRED
时:
<tx:method name="do*" propagation="REQUIRED" />
考虑一个场景:
来电者-------&gt; [交易方法1(m1)] ----------&gt; [事务 方法2(平方米)]
在Spring管理的环境中,logical
和physical
交易之间存在差异。为应用此设置的每个方法创建logical
事务范围。方法logical
的{{1}}交易范围与m1
不同。每个m2
事务可以单独确定其自己的仅回滚状态。使用此设置,外部事务范围(m1的范围)在逻辑上独立于内部事务范围(m2的范围)。
但是所有这些范围都映射到相同的logical
事务。因此,如果内部事务被标记为回滚,则它会影响外部事务的提交机会(即使外部事务没有抛出异常)。
现在,如果从内部事务抛出异常并且标记为回滚。但是外部事务没有抛出异常,所以它还没有决定回滚本身,因此回滚(由内部事务范围静默触发)是意外的。此时会抛出相应的physical
。
因此,如果内部事务(外部调用者不知道)默认将事务标记为仅回滚,则外部调用者如果仍调用commit,则会收到UnexpectedRollbackException
。这表示外部调用者执行了回滚而不是提交。这是一个预期的行为,让事务的调用者知道存在异常并且事务被回滚。