Quarkus集成测试中持久化对象未写入PostgreSQL数据库问题
问题分析与解决方案
核心问题
你遇到的问题根源是事务边界与Hibernate缓存的交互冲突:
@BeforeEach中的Company持久化未纳入测试事务上下文,导致测试方法无法读取到数据;- 持久化后调用
findById()能返回对象,是因为Hibernate一级缓存(会话缓存)直接返回了未提交到数据库的对象,而非从数据库读取; - 测试代码存在笔误:
reposiitory.findById应为repository.findById,这会直接导致测试失败。
具体修复步骤
1. 修正代码笔误
将测试方法中的错误代码:
UserEntity user2 = reposiitory.findById(user.getId());
改为:
UserEntity user2 = repository.findById(user.getId());
2. 强制刷新持久化操作到数据库
在persistUser和persistCompany方法中添加flush(),确保对象从Hibernate缓存写入数据库:
@ApplicationScoped public class UserRepository implements PanacheRepositoryBase<UserEntity, Long> { @Transactional public UserEntity persistUser(UserEntity user) { persist(user); flush(); // 强制同步到数据库 return findById(user.getId()); } }
CompanyRepository做同样调整:
@ApplicationScoped public class CompanyRepository implements PanacheRepositoryBase<CompanyEntity, Long> { @Transactional public CompanyEntity persistCompany(CompanyEntity company) { persist(company); flush(); return findById(company.getId()); } }
3. 确保@BeforeEach在测试事务上下文内执行
给setup方法添加@Transactional注解,让Company的持久化操作纳入测试事务范围:
@BeforeEach @Transactional void setup() { company = companyRepo.persistCompany(createCompany()); }
4. 可选:用Optional查询提升严谨性
建议使用findByIdOptional替代findById,避免空指针异常:
@Test void test_persistUser() { UserEntity user = repository.persistUser(createUser(company, true, true)); assertNotNull(user); Optional<UserEntity> user2Opt = repository.findByIdOptional(user.getId()); assertTrue(user2Opt.isPresent()); UserEntity user2 = user2Opt.get(); assertNotNull(user2); }
补充说明
@QuarkusTransactionalTest默认会为每个测试方法创建独立事务,并在测试结束后自动回滚。上述调整确保所有操作都在同一个测试事务内执行,同时通过flush()强制同步缓存到数据库,避免缓存与数据库状态不一致的问题。
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

