0

我有一个 JUnit 测试,我在测试用例的开头设置测试数据,然后在相同的测试方法中测试测试用例的条件。测试测试用例条件的查询是本机查询。我知道我必须显式调用 EntityManager.flush() 才能将我的插入/更新立即写入数据库,因为它们在同一个事务中。此外,我注意到我可以用 JPA 查询替换 entityManager.flush(),这似乎可以达到同样的效果。我听说 JPA 会在同一个事务中缓存 DB 操作,直到需要立即执行它们,例如发出选择查询时。所以这一切都是有道理的。我的问题是,为什么不 这种行为是否也适用于本机查询?在这里,我的本机查询不会触发 testSetup() 中插入/更新的立即执行,从而导致我的断言失败。

@Test
@Transactional
public void testCase() {
    testSetup();
    entityManager.flush();  // can be replaced with entityManager.createQuery("from Person");

    List resultList = entityManager.createNativeQuery("select * from Person").getResultList();
    Assert.assertTrue(resultList.size() == 1);
}
4

1 回答 1

1

tl;dr - 本机查询绕过持久性上下文和缓存。

createNativeQuery显然,这包括您通过调用创建的查询。但是批量更新(UPDATEDELETE),虽然用 JPQL 表示,但由提供者转换为本地查询,并绕过持久性上下文和缓存。

因此刷新或执行其他查询不会产生预期的效果。

此外,如果您的本机查询更改了在当前持久性上下文中管理或缓存的实体上的数据,则这些实体将不会自动刷新并且会变得陈旧。

于 2013-10-23T15:09:07.683 回答