为何调用JPA的findAll()会触发事务提前提交?
问题:JPA中findAll()为何会触发事务提前提交?
代码片段
@Transactional public boolean updateAdminUser(Long userId, CreateUpdateAdminUserDto createUpdateAdminUserDto) { //other code adminUserRoleRepository.deleteAdminUsersRolesByAdminUserId(userId); adminUserRoleRepository.findAll(); adminUserRepository.save(adminUser); }
问题描述
原本在删除数据后执行新增操作时,因删除未提交导致数据重复;添加adminUserRoleRepository.findAll()后,删除操作会提前提交,新增数据成功写入数据库,想请教为何JPA的findAll()会触发事务提前提交?
回答
核心原因是JPA的自动刷新(Auto Flush)机制:
- JPA默认会把事务内的增删改操作暂存在持久化上下文的缓存中,直到事务提交时才一次性刷入数据库,以此提升性能。
- 但当执行可能受当前未提交修改影响的查询时,JPA会自动触发flush操作,把缓存里的修改提前刷到数据库,确保查询结果能反映事务内的最新状态,避免读取到过期数据。
- 你调用的
adminUserRoleRepository.findAll()正好属于这类查询:它查询的是刚执行过delete操作的admin_user_role表,Hibernate(Spring Data JPA的默认实现)会检测到这个查询依赖于未提交的删除操作,因此自动执行flush,把删除操作提前提交到数据库。
至于之前没加findAll()时的重复问题,是因为删除操作还停留在缓存里,新增操作基于数据库的旧状态(未感知到已删除的记录),导致逻辑上出现重复数据。
内容的提问来源于stack exchange,提问作者黃奕翔
相关产品推荐
相关产品推荐

