一尘不染

从另一个线程(可运行)调用@Transactional方法

java

有没有简单的解决方案,可以在新线程中使用JPA将数据保存到数据库中?

我基于Spring的Web应用程序允许用户管理计划的任务。在运行时,他可以创建和启动预定义任务的新实例。我正在使用spring的TaskScheduler,并且一切正常。

但是我需要将每个被激发任务的布尔结果保存到数据库中。我怎样才能做到这一点?

编辑:我必须概括我的问题:我需要从任务在我的@Service类上调用方法。因为在保存到数据库之前必须对任务结果进行“处理”。

编辑2:我有问题的代码的简化版本在这里。从调度程序调用saveTaskResult()时,将打印出消息,但没有任何内容保存到db中。但是,每当我从控制器调用saveTaskResult()时,记录都将正确保存到数据库中。

@Service
public class DemoService {

    @Autowired
    private TaskResultDao taskResultDao;

    @Autowired
    private TaskScheduler scheduler;

    public void scheduleNewTask() {
        scheduler.scheduleWithFixedDelay(new Runnable() {

            public void run() {
                // do some action here
                saveTaskResult(new TaskResult("result"));
            }

        }, 1000L);
    }

    @Transactional
    public void saveTaskResult(TaskResult result) {
        System.out.println("saving task result");
        taskResultDao.persist(result);
    }

}

阅读 786

收藏
2020-12-03

共1个答案

一尘不染

代码的问题在于,您希望在调用时启动事务saveTaskResult()。这不会发生,因为Spring使用AOP来启动和停止事务。

如果您从bean工厂获得事务性Spring
bean的实例,或者通过依赖注入,则实际上得到的是bean周围的代理。该代理在调用实际方法之前启动事务,并在方法完成后提交或回滚事务。

在这种情况下,无需调用事务代理即可调用bean的本地方法。将saveTaskResult()方法(带有注释@Transactional)放入另一个Spring
bean。将另一个Spring bean注入DemoService,然后从DemoService调用另一个Spring bean,一切都会好起来的。

2020-12-03