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(); } }
已做的排查和奇怪的发现
- 数据源是标准配置,没有任何特殊定制;
- 同一个Service被
@RestController调用时,saveAll()完全正常,批量插入的记录能实时在数据库中查到; - 我做了个测试:在定时任务的调用流程里,单独调用
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
相关产品推荐
相关产品推荐

