JPA:本机查询不会在同一事务中触发缓存插入/更新的执行

时间:2013-10-23 14:54:00

标签: spring jpa junit spring-transactions spring-test

我有一个JUnit测试,我在测试用例的开头设置测试数据,然后在同一测试方法中测试测试用例的条件。测试测试用例条件的查询是本机查询。我知道我必须显式调用EntityManager.flush()才能将我的插入/更新立即写入数据库,因为它们在同一个事务中。另外,我注意到我可以用一个JPA查询替换entityManager.flush(),这似乎可以达到同样的效果。我听说JPA会在同一个事务中缓存数据库操作,直到需要立即执行它们,例如发出select查询时。所以这一切都有道理。我的问题是,为什么这种行为也不适用于本机查询?在这里,我的本机查询不会在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);
}

1 个答案:

答案 0 :(得分:1)

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

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

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

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