Java 将spring事务传播到同级调用
考虑到我有下面的春豆 复合服务:Java 将spring事务传播到同级调用,java,spring,transactions,Java,Spring,Transactions,考虑到我有下面的春豆 复合服务: @Service public class CompositeService { @Resource private ServiceA serviceA; @Resource private ServiceB serviceB; public ResultBean compositeMethod() { ResultBean result = new ResultBean(); res
@Service
public class CompositeService {
@Resource
private ServiceA serviceA;
@Resource
private ServiceB serviceB;
public ResultBean compositeMethod() {
ResultBean result = new ResultBean();
result.setA(serviceA.getA());
result.setB(serviceB.getB());
return result;
}
}
@Service
public class ServiceA {
@Transactional
@Cacheable
A getA() {
// calls DAO layer and makes a query to the database
}
}
@Service
public class ServiceB {
@Transactional
@Cacheable
B getB() {
// calls DAO layer and makes a query to the database
}
}
服务A:
@Service
public class CompositeService {
@Resource
private ServiceA serviceA;
@Resource
private ServiceB serviceB;
public ResultBean compositeMethod() {
ResultBean result = new ResultBean();
result.setA(serviceA.getA());
result.setB(serviceB.getB());
return result;
}
}
@Service
public class ServiceA {
@Transactional
@Cacheable
A getA() {
// calls DAO layer and makes a query to the database
}
}
@Service
public class ServiceB {
@Transactional
@Cacheable
B getB() {
// calls DAO layer and makes a query to the database
}
}
服务b:
@Service
public class CompositeService {
@Resource
private ServiceA serviceA;
@Resource
private ServiceB serviceB;
public ResultBean compositeMethod() {
ResultBean result = new ResultBean();
result.setA(serviceA.getA());
result.setB(serviceB.getB());
return result;
}
}
@Service
public class ServiceA {
@Transactional
@Cacheable
A getA() {
// calls DAO layer and makes a query to the database
}
}
@Service
public class ServiceB {
@Transactional
@Cacheable
B getB() {
// calls DAO layer and makes a query to the database
}
}
可缓存方面具有更高的顺序
这段代码的问题是,如果两个服务中的缓存未命中,它将启动两个事务(并从池中获取两个连接)。
我可以配置Spring在这个用例中使用相同的事务吗?
即,将事务从ServiceA传播到CompositeService,然后再传播到ServiceB
我无法将CompositeService设置为transactional,因为我不想在ServiceA和ServiceB中缓存命中的情况下启动事务(并从池借用连接)您可以做的是也可以使用
@transactional
注释compositeMethod。事务的默认传播级别设置为“必需”
支持当前事务,如果不存在,则创建新事务
因此,尽管这不完全是您所要求的,但事务划分从compositeMethod开始,但它应该是您想要的语义。只有在所有事务都在同一事务下时,Spring才会传播事务。因此,简单的回答是,您应该使用
@Transactional
注释您的复合服务
@Service
public class CompositeService {
@Transactional
public ResultBean compositeMethod() {
ResultBean result = new ResultBean();
result.setA(serviceA.getA());
result.setB(serviceB.getB());
return result;
}
}
通常这足够快,因为它只从底层连接池进行签出。但是,如果您遇到延迟或不总是需要连接,您可以将实际的数据源
包装在一个文件夹中。这将在第一次需要时获得连接。我无法将CompositeService设置为事务性,因为我不想在ServiceA和ServiceBmhm中发生缓存命中时启动事务(并从池借用连接),您的问题更有趣的是,第一眼就能看出它只有在封闭方法(在CompositeService
中)是事务性的情况下才有效。如果这些都是您担心的事情,那么为什么在几毫秒内签出连接会有问题呢?IMHO您担心的事情是错误的。@M.Deinum在我的特殊情况下,数据库部署在另一个区域的数据中心,java应用程序和数据库之间的延迟为300毫秒?您有一个连接池,因此连接已经存在。唯一发生的事情是从池中签出连接。没有别的了。这应该只需要~1ms.。@M.Deinum验证查询(如从dual中选择1)需要300ms才能执行。我知道我可以删除验证查询,使用体面的池并在我的dao层中处理适当的异常-但问题是Spring是否可以为我这样做?您可以尝试的一件事是将数据源
包装在一个只有在需要时才能获得连接的数据库中。这是创建第一条语句的时间。