You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中@Scheduled任务调用saveAll()挂起,但@RestController调用正常的问题求助

Spring Boot中@Scheduled任务调用saveAll()挂起,但@RestController调用正常的问题求助

我现在碰到一个特别诡异的问题,Spring Boot项目里同一个业务服务的saveAll()方法,被@RestController调用时完全正常,但被@Scheduled定时任务触发就直接挂起——没有任何异常日志,代码卡着不动,完全找不到头绪,想请教大家有没有类似的排查思路或者解决方向?

项目基本情况

我们的项目是多模块结构:

  • parent(无业务代码)
    • api-service(对外提供API的模块)
    • schedule-service(定时任务模块)
    • common(存放Service、Repository、实体类等公共代码)
      所有业务代码都在com.xx.yyy及其子包下。

定时任务模块启动类

启动类配置看起来很标准,已经开启了调度和必要的扫描:

package com.xx.yyy;

@SpringBootApplication(scanBasePackages = { "com.xx.yyy"})
@EntityScan("com.xx.yyy")
@EnableFeignClients
@EnableScheduling
public class Main {
    public static void main(final String[] args) {
        SpringApplication.run(Main.class, args);
    }
}

核心代码细节

Service层实现

最初的Service逻辑很简单,循环读取数据后批量保存:

package com.xx.yyy.service;

@Service
public class MyServiceImpl implements MyService {

    @Autowired
    MyEntityRepository myEntityRepository;

    public int importStuff() {
        do {
            List<MyEntity> entities = readStuff();
            log.info("About to save " + entities.size());
            myEntityRepository.saveAll(entities);
            log.info("saved");
        } while (moreStuff());
    }
}

后来我尝试手动加了@Transactional注解和强制flush(),结果还是挂起:

package com.xx.yyy.service;

@Service
public class MyServiceImpl implements MyService {

    @Autowired
    MyEntityRepository myEntityRepository;

    public void importStuff() {
        do {
            List<MyEntity> entities = readStuff();
            log.info("About to save " + entities.size());
            mySaveAll(entities);
            log.info("saved");
        } while (moreStuff());
    }

    @Transactional
    public void mySaveAll(List<MyEntity> entities) {
        myEntityRepository.saveAll(entities);
        myEntityRepository.flush();
    }
}

Repository层实现

Repository是标准的Spring Data JPA接口:

package com.xx.yyy.dao;

@Repository
public interface MyEntityRepository extends JpaRepository<MyEntity, MyEntityCompositeId> {
}

定时任务触发类

定时任务通过@Scheduled配置触发,我还加了@Async注解,但问题依旧:

package com.xx.yyy.scheduler;

@Component
public class MyScheduler {

    @Autowired
    private MyService myService;

    @Async
    @Scheduled(cron="xxx")
    public void myJob() {
        myService.importStuff();
    }
}

已做的排查和奇怪的发现

  1. 数据源是标准配置,没有任何特殊定制;
  2. 同一个Service被@RestController调用时,saveAll()完全正常,批量插入的记录能实时在数据库中查到;
  3. 我做了个测试:在定时任务的调用流程里,单独调用save(entities.get(0))保存单个实体,居然能成功写入数据库,日志也能正常打印到“saved”,但一调用saveAll()就直接卡着不动,后续日志永远打不出来,也没有任何异常抛出:
// 这段在定时任务里能正常执行完成
log.info("saving " + entities.get(0));
myEntityRepository.save(entities.get(0));
log.info("saved " + entities.get(0));

// 但下面这段直接挂起,永远到不了后续的日志
log.info("About to save " + entities.size());
mySaveAll(entities);
log.info("saved"); // 这条日志永远打不出来

想请教的问题

现在完全搞不懂:为什么单个save()在定时任务里正常,saveAll()却只有Controller调用时才正常?有没有什么排查方向?或者有没有办法手动创建EntityManager来绕开这个问题,同时还能继续用Spring Data JPA提供的CRUD能力?

我们用的是Spring Boot 2.7版本,Java 8。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.08 14:43:09