从不包含任何脏对象的实体管理器提交事务时会发生什么?会不会没有向数据库发送 COMMIT 命令?
我时不时有一些测试用例在没有合理原因的情况下失败。经过一番调查,我现在有了一个我想在这里证实的理论。
我有一个小型夹具框架来为每个测试准备数据库上的数据。夹具使用这种方法使用 JPA (Hibernate) 将对象存储到数据库:
public <R> R doInTransaction(final Function<EntityManager, R> whatToDo) {
final EntityManager em = emf.createEntityManager();
final R result;
try {
try {
em.getTransaction().begin();
result = whatToDo.apply(em);
em.getTransaction().commit();
} finally {
if (em.getTransaction().isActive()) {
em.getTransaction().rollback();
}
}
} finally {
em.close();
}
return result;
}
因此,fixture 调用此方法传递 whatToDo 函数,其中对象被持久化,并且该方法围绕传递的函数包装事务。我失败的测试用例使用的夹具依赖于使用存储过程并直接通过 JDBC 存储对象的遗留代码,即em.persist()
我没有使用 ,而是在传递的函数中使用以下内容来调用存储过程:
em.unwrap(Session.class).doWork(connection -> {
// stored procedures are called here directly over JDBC
});
因此,我的理论是,在这种情况下,JPA 不会立即提交,因为 EntityManager 没有管理 JPA 脏对象。因此,实际提交仅在稍后发生,即在我的测试断言并且测试失败之后。可以吗?
当从 EntityManager 中“解包”连接时,Hibernate 的事务行为是什么?
我现在在em.flush()
之前添加了一个em.getTransaction().commit()
,它似乎有帮助,但我仍然不能 100% 确信这可以解决问题。有人可以确认吗?