字符串 Hibernate 事务

String Hibernate transactions

我继承了一个使用 Spring 和 Hibernate 的应用程序。我正在尝试创建一个新的 API 方法来执行一个工作单元。这个工作单元应该在单个数据库事务中完成,这样如果出现任何问题,所有更改都会回滚。

该应用程序似乎已设置为使用事务,因此我已将事务注释添加到我的新方法中。这是我的新方法的简化版本。

@Transactional(readOnly=false, propagation=Propagation.REQUIRES_NEW, rollbackFor={IllegalMemberException.class, InvalidPasswordException.class, IllegalDomainException.class})
private ApiResponse mergeUsersWork(Member fromMember, Member toMember) 
throws IllegalMemberException, InvalidPasswordException, IllegalDomainException 
{
    //Update the members details
    Date now = new Date();
    MemberPropertiesParameters mpp = new MemberPropertiesParameters();
    mpp.set(MemberField.LLI, now);
    mpp.set(MemberField.LLO, now);
    fromMember = memberManager.updateMember(fromMember, mpp);

    //Enter the from user GUID - we should be able to use this to back out any cock-ups 
    toMember.setObject(MemberField.MERGED_FROM_MEMBER_ID, fromMember.getObject(MemberField.MERGED_FROM_MEMBER_ID));
    memberManager.updateMember(toMember, null);

    if(1==1) {
        throw new RuntimeException("Blah Blah Blah");
    }

    ApiResponse apiResponse = new ApiResponse("members");
    apiResponse.getResponseHeader().setDetail("Users merged successfully.");
    apiResponse.setResponseData(new ApiResponseData(MemberTO.createTO(toMember, toMember.getOrganisation())));
    return apiResponse;
}

运行 通过调试器我发现第 10 行的成员更新

fromMember = memberManager.updateMember(fromMember, mpp);

在行 returns 后立即写入数据库,而不是在方法结束时。因此,之后抛出的任何异常都无效,因为提交似乎已经发生。我已经检查并删除了所有冲洗。 updateMember 方法签名按应有的方式传播事务

@Transactional(readOnly=false, propagation=Propagation.REQUIRED)
public Member updateMember(Member member, MemberPropertiesParameters args) 
throws IllegalMemberException, InvalidPasswordException 

我现在的知识已经达到极限了,我还没有花几个星期的时间来学习所有这些东西,我希望有人能给我指明正确的方向。

非常感谢

将某些内容写入数据库这一事实并不意味着您的事务已提交。 Flush 只是指示 hibernate 发出当前会话中执行的所有查询,但事务仍然可以回滚。

您可以调试代码并检查对 class 的调用是否包含在事务代理中。

还有一件事。 您的方法被声明为抛出异常。 任何 RuntimeException 都会触发回滚,而任何 checked Exception 都不会。 因此,如果 IllegalMemberException、InvalidPasswordException 是您必须添加的检查异常:

@Transactional(rollbackFor={IllegalMemberException.class, InvalidPasswordException.class})

编辑:

我以前没见过。你的方法是 private。它必须是 public 否则 spring 将无法应用处理事务的方面。

我不知道你是如何调用你的方法的,但交易是由代理处理的。这意味着即使您的方法是 public 并用 @Transactional 注释,但您从 class 中的非事务性方法调用它,也不会有事务!了解 spring AOP。

你真的会受到这样的影响吗?不可能。

您应该知道,@Transactional 注释将 wrap 目标方法放在 Spring Aspect 中。它将在 beforeafter 方法执行时被调用。

在之前 它将考虑是否有任何正在进行的事务以及什么是传播级别。如果加入的交易存在并且需要传播——它将在同一个交易中执行。另一方面,它会为目标方法创建新的特定方法。

之后-它将commit/rollback交易。

IF ANY 事务相关异常将发生 - 这将是 运行时异常,您不应该捕获它!

所以,如果你真的遇到这种情况,你应该调试你的方法周围的方面。此外,您的成员经理应该 update/commit/merge 在同一事务中 - 如果不相同,这就是为什么它会在目标方法执行结束之前更新您的模型。