在服务层,我有一些具有事务注释的方法。
@Transactional
public void process() throws ProcessPaymentException{
try{
.... do some operation
catch (ProcessPaymentException ppe) {
save db problem issue.
}
}
好像有问题,有回滚......并且数据库中没有保存任何内容......
ProcessPaymentException扩展异常
有没有办法在try中回滚进程但是在catch中进行保存?
修改
如果此链接正常,嵌套事务可能是一种解决方案 https://www.credera.com/blog/technology-insights/java/common-oversights-utilizing-nested-transactions-spring/
答案 0 :(得分:0)
因为try-catch的进程被同一个事务包装。 每当抛出异常时,事务管理器都会回滚。所以,不会保存任何东西。
有没有办法在try中回滚进程但是在catch中进行保存?
是。创建异常处理程序以在回滚后保存数据库问题。 这就是想法
@ControllerAdvice
public class HandlerName {
@ExceptionHandler(ProcessPaymentException.class)
public void saveDbIssue(ProcessPaymentException ex) {
// save db problem issue.
}
但只有在您想保存静态数据时它才有效。
答案 1 :(得分:0)
使用ControllerAdvise
的现有答案应该有助于正常设置传入请求通过Spring MVC(即通过Controller
)。
对于没有的情况,或者你不想将你的异常处理逻辑与Spring MVC联系起来,这里有一些我能想到的选择
(这里我假设你想依靠声明式事务控制而不是自己以编程方式控制事务)
单独的服务/组件以在不同的事务中保存错误。
简而言之,您可以拥有一个单独的服务,该服务通过传播REQUIRES_NEW
创建自己的事务。 e.g。
@Service
public class FooService
@Inject
private ErrorAuditService errorAuditService;
@Transactional
public void process() throws ProcessPaymentException{
try{
.... do some operation
catch (ProcessPaymentException ppe) {
errorAuditService.saveErrorAudit(ppe.getErrorText());
throw ppe; // I guess you want to re-throw the exception
}
}
}
@Service
public class ErrorAuditService
@Transactional(propagation=REQUIRES_NEW)
public void saveErrorAudit() {
// save to DB
}
}
更进一步,如果错误处理它对于不同的服务相同,您可以创建一个建议,当服务方法抛出异常时将调用该建议。在该建议中,您可以将错误保存在db中(使用ErrorAuditService
),然后重新抛出异常。