SpringBoot GET接口首次请求返回空数组问题求助
排查SpringBoot接口首次请求新websiteID返回空数组问题
可能的原因
- 数据持久化延迟:首次请求时,t1、t2模板的保存操作还未完成(比如事务未提交、异步执行),查询就已经触发,导致查不到数据。
- 缓存不一致:如果用了缓存,首次查询缓存为空返回空数组,保存后缓存没更新,第二次查询时缓存失效或直接查库,此时数据已写入。
- 事务边界错误:保存和查询操作在同一事务中,查询执行时保存的事务还没提交,数据库还没写入数据。
排查修复步骤
检查保存逻辑的同步性
查看Service层初始化模板的代码,确认是否用了@Async之类的异步注解。如果是异步执行,要么改成同步,要么在查询前等待异步任务完成,确保数据先写入数据库。验证事务提交时机
如果初始化模板和查询的逻辑在同一个方法里,检查事务配置。比如initTemplatesForNewWebsite方法加了@Transactional,但查询操作在同一个事务内执行,此时数据还没提交到数据库。解决方案是把查询逻辑移到事务外,或者拆分方法,让初始化和查询处于不同事务。排查缓存配置
若查询方法用了@Cacheable,首次查询会把空结果缓存起来,即使后面保存了数据,第二次请求才会重新查库。需要在初始化模板后,清除对应websiteID的缓存,或者用@CachePut更新缓存。比如在initTemplatesForNewWebsite方法上加@CacheEvict(value = "templateCache", key = "#websiteID")。加日志定位执行顺序
在保存方法结束、查询方法开始的地方打印日志,记录时间戳和websiteID,确认保存和查询的执行顺序,以及保存后数据库是否真的写入了数据。比如:// 保存后日志 log.info("已为websiteID: {} 初始化t1、t2模板", websiteID); // 查询前日志 log.info("开始查询websiteID: {} 的模板列表", websiteID);直接查数据库验证
首次请求接口后立刻查cookiebanner表,看t1、t2是否存在。如果数据库有数据但接口返回空,问题在查询或缓存;如果数据库没数据,说明保存逻辑有问题。
代码修复示例
@Service public class CookieBannerTemplateService { @Autowired private CookieBannerTemplateRepository repository; @Transactional public void initTemplatesForNewWebsite(String websiteID) { CookieBannerTemplate t1 = new CookieBannerTemplate(); t1.setWebsiteID(websiteID); // 设置t1属性 repository.save(t1); CookieBannerTemplate t2 = new CookieBannerTemplate(); t2.setWebsiteID(websiteID); // 设置t2属性 repository.save(t2); // 事务在此提交 } @Cacheable(value = "templateCache", key = "#websiteID") public List<CookieBannerTemplate> getAllTemplates(String websiteID) { if (!repository.existsByWebsiteID(websiteID)) { // 初始化后事务已提交,再查询 initTemplatesForNewWebsite(websiteID); // 清除缓存,确保下次查询能拿到新数据 Cache cache = cacheManager.getCache("templateCache"); if (cache != null) { cache.evict(websiteID); } // 重新查询 return repository.findByWebsiteID(websiteID); } return repository.findByWebsiteID(websiteID); } }
内容的提问来源于stack exchange,提问作者salinda yasas
相关产品推荐
相关产品推荐

