Spring @transactional没有为RuntimeException回滚

时间:2013-01-23 03:37:53

标签: spring db2

我的班级被定义为

@Transactional
@Service
public class InteractionHistoryServiceImpl implements InteractionHistoryService {

在类中,我有一个单独的方法,可以对下面的DB2存储过程进行4次单独的调用(伪):

@Override
public void createInteractionHistory(String userId, String userChannel,
        CreateInteractionHistoryRequestPayload requestPayload) {

dao.createInteractionHistory(userId, userChannel, viewableBy,
            interactCode, systemCreationDateTime, partyGrpId,
            interactionHistoryController);

dao.createInteractionHistoryDetails(userId, interactonDescription, interactionHistoryController);

dao.createInteractionHistoryDetailsLink(userId, componentId, objectId, objectType, correspondanceType, direction, interactionHistoryController);

dao.createInteractionHistoryDetailsLink(userId, componentId, documentId, DOCUMENT, correspondenceType, direction, interactionHistoryController);
}

现在在最后的调用中,我通过传递一个太大的字段宽度来强制数据库中的异常,因此它根本无法调用proc。捕获并将其转换为扩展RuntimeException的系统异常。

我在异常之后调试了这段代码,并将它提供给spring框架,似乎正在回滚。

当我检查基础表时,我可以看到所有先前存储的过程已成功但未回滚但最终调用未成功。

这使我的数据不一致并且令人头疼,因为我的理解是这些应该被处理全部或者没有提交/回滚。

我检查了存储过程,数据库中没有进行任何提交。

这里有什么想法吗?

1 个答案:

答案 0 :(得分:1)

您需要考虑您的交易边界。事务边界通常是执行BEGIN TRANSACTION和COMMIT / ROLLBACK语句的地方,并不完全取决于Spring,但也可能依赖于数据库实现。

在类级指定@Transactional表示该类的每个公共方法都有一个声明性事务边界(即:一个事务将在方法执行之前启动,在方法完成时调用/在发生异常时回滚)

在您的情况下,您似乎没有将4 createInteractionHistory 调用包含在一个单独的事务中 - 而是它们是4个单独的事务。因此,当最后一个失败时,前3个已经成功。

然而,即使您将所有这4个调用都包含在一个事务中,也不能保证所有SQL都将在一个事务中运行,因为它取决于您在存储过程中使用的代码以及DB2如何绘制事务边界

我建议你花一些时间在Spring事务边界和传播主题上 - 以及DB2事务。 Chapter 11 of the spring manual is a good reference.