As mentioned in [ HHH-8487 ] flush to the database is always done before accessing an entity via native SQL or HQL query when FlushModeType.AUTO is enabled.
So the @Version annotated property is always incremented when an update / merge with fetch with SQL of an entity occurs. But when doing an update to an entity and access it with {{entityManager.find( )}} the version is not incremented. So this behavior is inconsistent according to fetching over SQL. Should a flush to the database not also be done when calling {{entityManager.find( )}}?
Consider the testcase below as example: {code:java} package org.hibernate.bugs; import org.apache.log4j.Logger; import org.junit.After; import org.junit.Before; import org.junit.Test;
import javax.persistence.*;
import java.util.List;
import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat;
/** * This template demonstrates how to develop a test case for Hibernate ORM, using the Java Persistence API. */ public class JPAUnitTestCase {
Logger LOG = Logger.getLogger(JPAUnitTestCase.class);
private EntityManagerFactory entityManagerFactory; private EntityManager entityManager;
@Before public void init() { entityManagerFactory = Persistence.createEntityManagerFactory("templatePU"); entityManager = entityManagerFactory.createEntityManager();
// entityManager.setFlushMode(FlushModeType.COMMIT); entityManager.setFlushMode(FlushModeType.AUTO); }
@After public void destroy() { entityManager.close(); entityManagerFactory.close(); }
@Test public void hhh123Test() throws Exception {
entityManager.getTransaction().begin();
TableB b = new TableB(); b.setName("name b"); b.setDescription("Bsome description"); entityManager.persist(b);
TableA a = new TableA(); a.setName("name a"); a.setDescription("some description"); entityManager.persist(a);
{ a.setDescription("some new description 1"); entityManager.merge(a); TableA aFetch = entityManager.find(TableA.class, a.getId()); //version is not incremented, no flush assertThat(aFetch.getVersion(), is(0L)); }
{ // flush is executed and version is incremented Query query = entityManager.createQuery("select entity from table_a entity where id = :id").setParameter("id", a.getId()); TableA aFetch = (TableA) query.getSingleResult(); assertThat(aFetch.getVersion(), is(1L)); }
{ a.setDescription("some new description 2"); entityManager.merge(a); TableA aFetch = entityManager.find(TableA.class, a.getId()); //version is not incremented, no flush assertThat(aFetch.getVersion(), is(1L)); //do native query
List resultList = entityManager.createNativeQuery("select * from table_b", TableB.class).getResultList(); // flush is executed and version of TableA is incremented TableB bFetch = (TableB) resultList.get(0); assertThat(bFetch.getVersion(), is(0L)); aFetch = entityManager.find(TableA.class, a.getId()); assertThat(aFetch.getVersion(), is(2L)); }
LOG.info("Do commit");
entityManager.getTransaction().commit();
}
@Entity(name = "table_a") public static class TableA {
@Version @Column private Long version;
@Id @GeneratedValue @Column(name = "oId", updatable = false, nullable = false) private Long id;
@Column(nullable = true) private String name;
@Column(nullable = true) private String description;
public Long getVersion() { return version; }
public void setVersion(Long version) { this.version = version; }
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
@Override public String toString() { return String.format("TableA{version=%d, id=%d, name='%s', description='%s'}", version, id, name, description); } }
@Entity(name = "table_b") public static class TableB {
@Version @Column private Long version;
@Id @GeneratedValue @Column(name = "oId", updatable = false, nullable = false) private Long id;
@Column(nullable = true) private String name;
@Column(nullable = true) private String description;
public Long getVersion() { return version; }
public void setVersion(Long version) { this.version = version; }
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
@Override public String toString() { return String.format("TableB{version=%d, id=%d, name='%s', description='%s'}", version, id, name, description); } } } {code :java }
|
|