当前位置: 首页 > 知识库问答 >
问题:

在Spring Boot的for循环中使用REQUIRES_NEW的事务问题

蒋鹏鹍
2023-03-14
Transaction 1->
    loop -> transaction 2
         -> transaction 3
         -> ...
         -> transaction N
end of transaction 1

代码:

package test.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class DefaultController {

    @Autowired
    private Service1 service1;

    @ResponseBody
    @RequestMapping(method = RequestMethod.GET, path = "/")
    public ResponseEntity<?> test() throws Exception {
        service1.m1();
        return new ResponseEntity<>(HttpStatus.OK);
    }

}

此控制器调用一个服务:

package test.controller;

import java.util.Arrays;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

public class Service1 {

    @Autowired
    private Service2 service2;

    @Transactional(transactionManager = "transactionManager", propagation = Propagation.REQUIRED)
    public void m1() {

        List<Integer> list = Arrays.asList(1, 2);

        for (Integer j : list) {
            service2.m2(j);
            System.out.println("Exception for j = " + j);
        }
    }
}

这个service1调用一个service2,因为我知道Spring Boot AOP是基于代理的,所以我需要另一个bean来切换事务的传播:

package test.controller;

import java.util.Date;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import test.model.domain.Log;
import test.service.LogService;

@Service
public class Service2 {

    @Autowired
    private LogService logger;

    @Transactional(transactionManager = "transactionManager", propagation = Propagation.REQUIRES_NEW)
    public void m2(int i) {

        try {
            Log log = new Log();
            log.setDataMensagem(new Date());
            log.setDescricaoEnvioRecebimento("TEST");
            log.setDescricaoMensagem("TEST1");
            log.setIdMensagem("TEST2");
            log.setNomeFilaServico("TESTE3");
            logger.save(log);

            if (i == 2) {
                throw new RuntimeException();
            }
        } catch (Exception e) {
            System.out.println("RuntimeException in i = " + i);
        }
    }
}
package test.service;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import test.indicador.LogFilaServicoIndicador;
import test.model.domain.Log;
import test.repository.LogRepository;

@Service
@Transactional(transactionManager = "transactionManager", propagation = Propagation.REQUIRED)
public class LogService {

    private final LogRepository repository;

    public LogService(LogRepository repository) {
        this.repository = repository;
    }

    public Log save(Log logFilaServico) {
        return repository.save(logFilaServico);
    }
}
package test.repository;

import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import test.model.domain.Log;

@Repository
public interface LogRepository extends CrudRepository<Log, Long> {

}

共有1个答案

酆乐湛
2023-03-14

基于@jbnizet帮助,为了解决我需要的问题,我需要:

1)从m1()中删除@transactional(transactionManager=“transactionManager”,propagation=propagation.required)。

2)在m2()中将REQUIRES_NEW更改为REQUIRED,并从m2()中删除try catch块,在m1()中添加一个tryc catch块,因为它需要在不停止m1()执行的情况下处理异常。

public void m1() {

        List<Integer> list = Arrays.asList(1, 2);

        for (Integer j : list) {
            try {
                service2.m2(j);

            } catch (Exception e) {
                System.out.println("Exception for j = " + j);
            }
        }
    }
@Transactional(transactionManager = "transactionManager", propagation = Propagation.REQUIRED)
public void m2(int i) {

    Log log = new Log();
    log.setDataMensagem(new Date());
    log.setDescricaoEnvioRecebimento("TEST");
    log.setDescricaoMensagem("TEST1");
    log.setIdMensagem("TEST2");
    log.setNomeFilaServico("TESTE3");
    logger.save(log);

    if (i == 2) {
        throw new RuntimeException();
    }
}
 类似资料:
  • 问题内容: 我程序的想法是从以前保存在其他JFrame中的列表中选择一个名称。我想在标签中一个接一个地打印所有名称,它们之间的间隔很小,然后停在其中一个名称上。问题是,如果有多个代码,则无法正常工作。 这是我的代码的一部分: 问题答案: 不要使用循环或。只需使用即可。以下将导致每1000毫秒发生30 次迭代 。您可以相应地调整代码,使其适应每隔毫秒发生一次的情况。 如果需要,您可以在构造函数中设置

  • 我正在编写一个计算e^x值的方法。我在python中实现它的方式如下。 这将很好地返回e^x的值。但是,当我尝试在c#中实现相同的方法时,它没有输出与python中相同的值。以下是c#中的实现。 起初,这段代码的输出是一个无穷大符号。为了解决这个问题,我只是减少了循环运行的次数。在c#中,循环只运行10次,代码的输出非常接近于python中循环运行100次的输出。我的问题是,在不同的编程语言中,两

  • 问题内容: 我正在努力理解为什么我的代码处于一种状态而不是另一种状态。自从我讲完指针已经有一段时间了,所以我可能会生锈! 基本上,我有一个用于将对象存储在内存中的具有功能的存储库结构。 因此,它所做的全部工作就是将RW互斥锁锁定在其上,并将指针添加到由标识符引用的映射中。 然后,我得到了一个功能,该功能将基本上遍历这些对象的一部分,并将它们全部存储在存储库中。 上面的方法不起作用,看起来一开始一切

  • 我对使用高级for循环和试图使流程清晰感到困惑。 例如,我有这样的主数据帧: 我已经有一个包含每个元素的百分比表,如下所示: 我想计算每个键的条件概率,如下所示: 我对年份栏和元素感到困惑。如何使用for循环从主数据帧的列中提取元素? 我正在考虑另一种方法,但不知道如何开始。我从百分比表中得到key1和key2,然后创建一个年份的范围(range(1983,…),然后从条件概率函数中得到prob。

  • 本文向大家介绍Java中break、continue、return在for循环中的使用,包括了Java中break、continue、return在for循环中的使用的使用技巧和注意事项,需要的朋友参考一下 引言:在使用循环的时候,循环里面带有break、continue、return的时候经常弄混,今天特意整理了下,以待后用...  打印结果: 打印结果: 打印结果: 内层for循环结束… 打印

  • 问题内容: 如何在如下所示的循环中访问索引? 我想得到以下输出: 当我使用循环遍历它时,如何访问循环索引(在这种情况下为到)? 问题答案: 使用其他状态变量,例如索引变量(通常在或等语言中使用),被认为是非的。 更好的选择是使用 中都提供的内置函数: