2016-05-24 4 views
0

Warum es nicht funktioniert:JPA Update-Abfrage: Cache nicht ordnungsgemäß für ungültig erklärt

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

mit

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

und

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

Ergebnis ist

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

Es scheint, dass ein Cache vorhanden ist, der durch die Aktualisierungsabfrage nicht ungültig gemacht wird. checkResult und fancyEntity sind das gleiche Objekt. Erzwingen der Aktualisierung mit . Die seltsamste Sache ist, dass eine select ausgegeben wird, um checkResult (im ekclipselink log gesehen), noch wird sein Ergebnis nicht berücksichtigt. Gleiches Verhalten mit MySQL anstelle von HSQL.

Irgendein Hinweis darauf, was könnte falsch sein?

Antwort

1

Das ist eine Bulk-Update-Anweisung, wie die JPQL Sprache Referenz Hinweise:

Der Persistenzkontext ist mit dem Ergebnis der bulk aktualisieren oder löschen nicht synchronisiert. Vorsicht sollte verwendet werden, wenn Bulk Update- oder Löschvorgänge ausgeführt werden, da sie zu Inkonsistenzen zwischen der Datenbank und den Entitäten in der aktiven Persistenz Kontext führen können. Im Allgemeinen sollten Massenaktualisierungs- und -löschvorgänge nur in einer separaten Transaktion oder zu Beginn einer Transaktion ausgeführt werden (bevor auf Entitäten zugegriffen wurde, deren Status von solchen Operationen betroffen sein könnte).

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

Also das Verhalten, das Sie sehen, ist durchaus sinnvoll.