Java 带有捕获异常的Spring事务
最近,我一直在使用SpringBoot+SpringDataJPA+hibernate。我在spring事务中遇到了一个问题。这是我的服务课和两个问题:Java 带有捕获异常的Spring事务,java,spring,hibernate,jpa,spring-data,Java,Spring,Hibernate,Jpa,Spring Data,最近,我一直在使用SpringBoot+SpringDataJPA+hibernate。我在spring事务中遇到了一个问题。这是我的服务课和两个问题: @Transactional @Service class MyService { @Autowired private MyRepository myRep; public void method_A() { try { method_C(); .....
@Transactional
@Service
class MyService {
@Autowired
private MyRepository myRep;
public void method_A() {
try {
method_C();
.....
method_B();
} catch(Exception e) {}
}
public void method_B() {
Entity e = new Entity();
e.set(...);
myRep.save(e);
}
public void method_C() throws Exception {
....
}
}
1.如果方法method_C()
抛出异常,并且我希望捕获它并记录它,则不会在方法method_B()
中回滚事务,因为异常不会到达Spring framework。那么,为了捕获方法\u C()
的异常,同时不丢失方法方法\u B()
的回滚功能,我应该怎么做
2.考虑新方法<代码>方法>()<代码> < /P>
我希望在循环中调用
方法B()。如果方法\u B()
中发生异常,我希望回滚方法\u B()
的事务,但方法\u a()
不应退出,循环应继续执行。如何实现这一点?请执行以下操作,而不是抛出异常。(返回错误代码)
更新:我在发布后阅读了您的问题。如果从方法_A调用方法_b,则两者都在同一事务下。不幸的是,您无法单独回滚方法更改。如果它们都在一个服务类下,Spring将其视为一个事务。(所有方法)
你可以尝试以下方法
request to--> Controller() ---> (spring opens transaction) service_method_a(); (spring closes transaction)
Controller() ---> (spring opens transaction) service_method_c(); (spring closes transaction)
Controller() ---> (spring opens transaction) service_method_b(); (spring closes transaction)
return <--
更多信息
春天的故事。阅读本文下面的要点。在开发spring事务应用程序时,这些是最重要的。不要抛出异常,而是执行以下操作。(返回错误代码)
更新:我在发布后阅读了您的问题。如果从方法_A调用方法_b,则两者都在同一事务下。不幸的是,您无法单独回滚方法更改。如果它们都在一个服务类下,Spring将其视为一个事务。(所有方法)
你可以尝试以下方法
request to--> Controller() ---> (spring opens transaction) service_method_a(); (spring closes transaction)
Controller() ---> (spring opens transaction) service_method_c(); (spring closes transaction)
Controller() ---> (spring opens transaction) service_method_b(); (spring closes transaction)
return <--
更多信息
春天的故事。阅读本文下面的要点。这些在开发spring事务应用程序时最为重要。我通过这种方式解决了我的两个问题:创建了另一个@Service
类,并将方法B()移入其中。我已经将这个类注释为@Transactional
。现在方法方法A()
如下所示:
public void method_A() {
for(...) {
...
try {
anotherService.method_B();
} catch (Exception e) {
logger.error(...);
}
}
}
如果method_B()
方法中发生RuntimeException
,则会正确记录该异常,回滚method_B()
的事务,并继续循环。谢谢大家的回复。我这样解决了我的两个问题:创建了另一个@Service
类,并将方法B()
移入其中。我已经将这个类注释为@Transactional
。现在方法方法A()
如下所示:
public void method_A() {
for(...) {
...
try {
anotherService.method_B();
} catch (Exception e) {
logger.error(...);
}
}
}
如果method_B()
方法中发生RuntimeException
,则会正确记录该异常,回滚method_B()
的事务,并继续循环。谢谢大家的回复。Zeus,谢谢你的回复,但是method_B()
在异常情况下不会回滚,因为你已经用try-catch块包围了它的身体。值得一试,谢谢。另外,我想问一下你的陈述“如果你从方法A调用方法b,两者都在同一事务下。不幸的是,你不能单独回滚方法b的更改。如果它们都在一个服务类下,Spring将其视为一个事务。”如果这些方法在同一事务下,那么,为什么我们可以在方法(而不是类)之前添加带有不同参数(传播、隔离等)的@Transactional
注释呢?是因为我们希望不同方法中的事务必须有不同的行为吗?@polis我已经更新了答案。请参考最后的链接来解释我想说的话。它已经在某个地方得到了回答,所以,我不想再费劲解释了。宙斯,谢谢你的回答,但是method_B()
在异常情况下不会回滚,因为你已经用try-catch块包围了它的身体。值得一试,谢谢。另外,我想问一下你的陈述“如果你从方法A调用方法b,两者都在同一事务下。不幸的是,你不能单独回滚方法b的更改。如果它们都在一个服务类下,Spring将其视为一个事务。”如果这些方法在同一事务下,那么,为什么我们可以在方法(而不是类)之前添加带有不同参数(传播、隔离等)的@Transactional
注释呢?是因为我们希望不同方法中的事务必须有不同的行为吗?@polis我已经更新了答案。请参考最后的链接来解释我想说的话。它已经在某个地方得到了回答,所以,我不会再费劲地解释它了。不要捕获异常,spring无论如何都会记录异常,包括完整的堆栈跟踪,所以为什么要自己动手呢。对于选项2,只需在For循环中放置一个try/catch。方法B仍按原样运行(包括回滚),方法a仍在继续。如果您想要一些额外的异常处理,您可以总是编写一个后抛出方面来进行日志记录,或者添加一个catch,但总是重新抛出异常(但由于Spring已经记录了,这将是一个冗余的异常)。如果我在循环中添加try catch
块,则事务不会在方法_B()
中回滚。实体被保存并提交到数据库。这里的假设是methodA不在事务中,只有MethodB。您的意思是,如果只在methodmethod_B()
之前写入@Transactional
,它的行为应该像您所说的那样?不,因为这将是一个内部方法调用,因为Spring默认情况下,使用代理将根本没有事务。您可以在使用提前期或编译期编织时执行此操作