JPA更新查询:缓存未正确无效 [英] JPA update query: cache not properly invalidated

查看:204
本文介绍了JPA更新查询:缓存未正确无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么不起作用:

@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();
}

with

@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

似乎有一些更新查询未使之无效的缓存。 checkResult fancyEntity 是同一对象。使用 entityManager.refresh(checkResult)强制刷新。最奇怪的是,发出了 select 来检索 checkResult (在eclipselink日志中可见),但其结果仍然是没有考虑在内。使用MySQL而不是HSQL的行为相同。

It seems there is some cache that is not invalidated by the update query. checkResult and fancyEntity are the same object. Forcing the refresh using entityManager.refresh(checkResult). The weirdest thing is that a select is issued for retrieving checkResult (seen in the eclipselink log), still its result is not taken into account. Same behavior using MySQL rather than HSQL.

关于可能出问题的任何提示吗?

Any hint on what could be wrong ?

推荐答案

这是一个批量更新语句,正如JPQL语言参考所指出的那样:

That is a bulk update statement, As the JPQL language reference notes:


持久性上下文不是与
批量更新或删除的结果同步
。执行批量
更新或删除操作时应谨慎,因为它们可能会导致数据库和活动持久化
上下文中的实体之间的
不一致
。通常,批量更新和删除操作仅应在单独的事务内或
事务的开始处执行
(在访问状态可能为
的实体之前) 。

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

所以您所看到的行为很有道理。

So the behaviour you are seeing makes perfect sense.

这篇关于JPA更新查询:缓存未正确无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆