JPA 更新查询:缓存未正确失效

JPA update query: cache not properly invalidated

为什么不起作用:

@Test
public void test() {
    EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("test-pu");
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    String id = "id";
    long value = 1234L;

    entityManager.getTransaction().begin();

    FancyEntity fancyEntity = new FancyEntity(id);
    entityManager.persist(fancyEntity);
    int updateCount = entityManager.createQuery("update FancyEntity item set item.value = ?2 where item.id = ?1").setParameter(1, id).setParameter(2, value).executeUpdate();
    assertEquals(1, updateCount);

    FancyEntity checkResult = entityManager.find(FancyEntity.class, id);
    assertEquals(1234L, checkResult.getValue()); // <- this assert fails

    entityManager.getTransaction().commit();
}

@Entity
public class FancyEntity {
    @Id
    private String id;
    @Column
    private long value;
    public FancyEntity(String id) {
        this.id = id;
        this.value = 0;
    }
    public FancyEntity() {
    }
    public long getValue() {
        return value;
    }
}

<persistence-unit name="test-pu"
                  transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
    <class>com.fancypackage.FancyEntity</class>

    <properties>
        <property name="eclipselink.logging.level" value="SEVERE"/>
        <property name="javax.persistence.jdbc.driver" value="org.hsqldb.jdbcDriver" />
        <property name="javax.persistence.jdbc.url" value="jdbc:hsqldb:mem;sql.enforce_strict_size=true;hsqldb.tx=mvcc" />
        <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
        <property name="eclipselink.ddl-generation.output-mode" value="database" />
        <property name="eclipselink.logging.level.sql" value="FINE"/>
        <property name="eclipselink.logging.parameters" value="true"/>
    </properties>
</persistence-unit>

结果是

java.lang.AssertionError: 
Expected :1234
Actual   :0

似乎有一些缓存没有被更新查询失效。 checkResultfancyEntity 是同一个对象。使用 entityManager.refresh(checkResult) 强制刷新。最奇怪的是,发出 select 以检索 checkResult(在 eclipselink 日志中看到),但仍未考虑其结果。使用 MySQL 而不是 HSQL 的相同行为。

有什么可能出错的提示吗?

那是批量更新语句,如JPQL语言参考注释:

The persistence context is not synchronized with the result of the bulk update or delete. Caution should be used when executing bulk update or delete operations because they may result in inconsistencies between the database and the entities in the active persistence context. In general, bulk update and delete operations should only be performed within a separate transaction or at the beginning of a transaction (before entities have been accessed whose state might be affected by such operations).

https://docs.oracle.com/html/E24396_01/ejb3_langref.html#ejb3_langref_bulk_ops)

因此,您看到的行为非常合理。