Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将spring事务传播到同级调用_Java_Spring_Transactions - Fatal编程技术网

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是否可以为我这样做?您可以尝试的一件事是将
数据源
包装在一个只有在需要时才能获得
连接的数据库中。这是创建第一条
语句的时间。