字符串 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
中。它将在 before 和 after 方法执行时被调用。
在之前 它将考虑是否有任何正在进行的事务以及什么是传播级别。如果加入的交易存在并且需要传播——它将在同一个交易中执行。另一方面,它会为目标方法创建新的特定方法。
在之后-它将commit/rollback交易。
IF ANY 事务相关异常将发生 - 这将是 运行时异常,您不应该捕获它!
所以,如果你真的遇到这种情况,你应该调试你的方法周围的方面。此外,您的成员经理应该 update/commit/merge 在同一事务中 - 如果不相同,这就是为什么它会在目标方法执行结束之前更新您的模型。
我继承了一个使用 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
中。它将在 before 和 after 方法执行时被调用。
在之前 它将考虑是否有任何正在进行的事务以及什么是传播级别。如果加入的交易存在并且需要传播——它将在同一个交易中执行。另一方面,它会为目标方法创建新的特定方法。
在之后-它将commit/rollback交易。
IF ANY 事务相关异常将发生 - 这将是 运行时异常,您不应该捕获它!
所以,如果你真的遇到这种情况,你应该调试你的方法周围的方面。此外,您的成员经理应该 update/commit/merge 在同一事务中 - 如果不相同,这就是为什么它会在目标方法执行结束之前更新您的模型。