2

考虑以下代码片段。(我使用的是 Spring 3.1 和 Hibernate 3.6)

@Override
@Transactional
public <T extends Termination> void progressToPendingStage(Class<T> entity,
        Long terminationId, String userName) throws Exception {

    Termination termination = findTerminationById(entity, terminationId);
    //TODO improvise such that email does not get sent if data is not saved
    if (termination.getStatus().equals(TerminationStatus.BEING_PREPARED.toString())) {
        termination.setStatus(TerminationStatus.PENDING.toString());
        termination.setSubmittedDate(new Date());
        termination.setSubmittedBy(userName);
        saveOrUpdateTermination(termination);
        //Send an email to SAS
        emailHelper.configureEmailAndSend(termination);
    }   

}

上述方法的单元测试表明,无论 saveOrUpdateTermination(termination) 是否引发异常,都会发送电子邮件。在进一步的测试和一些研究中,我发现这种行为是预期的行为。这不是业务规则所希望的。只有在成功保存终止记录时才应发送电子邮件。关于如何使其以所需方式运行的任何建议?我能想到的一种方法是让调用者处理 progressToPendingStage 方法抛出的异常,如果没有抛出异常,则发送电子邮件。我是在正确的轨道上还是我们可以改变@Transaction 的行为方式。

4

1 回答 1

0

我已经通过围绕这个问题进行设计来解决这个问题。发送电子邮件从来都不是交易的一部分。我创建了一个执行后保存任务的对象。该对象将捕获保存终止时引发的异常,如果没有引发异常,我将触发一封电子邮件发送出去。也可以把它放在一个 Spring Aspect 中,它可以在成功保存后成功返回时执行。

经验教训:不要包含不属于标有@transaction 的方法中的步骤。如果它包含在事务中,Spring 将静默处理异常并且在事务完成之前不会抛出异常。简而言之,如果一个方法用@Transaction 注释,该方法中的每一行都将被执行,即使方法中间的一行抛出异常。

于 2013-08-28T08:08:31.867 回答