最近,我一直在使用Spring boot + spring数据jpa + hibernate。我遇到了春季交易的一个问题。这是我的服务类和两个问题:
@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框架。那么我该怎样做才能从method_C()
中捕获异常,同时又不会失去方法method_B()
的回滚能力?
2.考虑新方法method_A()
。
public void method_A() {
for(...) {
...
...
method_B();
}
}
我想在循环中调用method_B()
。如果method_B()
中发生异常,我想要回滚method_B()
的事务,但method_A()
不应该退出,循环应继续激活。我怎样才能做到这一点?
答案 0 :(得分:4)
我用这种方式解决了我的两个问题:创建了另一个@Service
类并将method_B()
移入其中。我已将此课程注释为@Transactional
。现在方法method_A()
看起来像这样:
public void method_A() {
for(...) {
...
try {
anotherService.method_B();
} catch (Exception e) {
logger.error(...);
}
}
}
如果RuntimeException
方法中出现method_B()
,则会异常记录异常,回滚method_B()
的事务并且循环连续。谢谢大家的回复。
答案 1 :(得分:0)
而不是抛出异常,请执行以下操作。 (返回错误代码)。
更新:我在发帖后阅读了您的问题。如果从method_A调用method_b,则两者都处于同一事务中。遗憾的是,您无法单独回滚method_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 <--
我希望它有意义
如果它们喜欢回滚,你的每个方法a,b,c都会抛出异常。
<强>更新强> 另一种方法。这个好多了。
如果您的每个方法都在不同的服务中,那么您可以使用spring的以下注释在不同的事务边界中运行每个方法
p v serviceA{
@transactional
method_a(){
serviceb.method_b();
}
}
p v serviceB{
@Transactional(propagation=Propagation.REQUIRED)
method_b(){
}
}
更多信息here
春季交易故事here。阅读本文下面的要点。在开发spring transactional应用程序时,这些是最重要的。