JPA update query: cache not properly invalidated

不羁岁月 提交于 2019-12-02 17:04:14

问题


Why doesn't it work:

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

and

<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>

Result is

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

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 ?


回答1:


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.



来源:https://stackoverflow.com/questions/37407257/jpa-update-query-cache-not-properly-invalidated

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!