My team uses hibernate-core and hibernate-c3p0. we recently tried to upgrade from version 5.4.1.Final to latest (5.4.14.Final) however this caused our version field to stop updating. Dug in and found this change starts happening on version 5.4.4.Final.
Hibernate usage: We use hibernate with queryDSL and javax.persistence We use javax.Persistence to create an entityManagerFactory with a set of hibernate properties
{code:java} ImmutableMap.Builder<String, String> properties = ImmutableMap.<String, String>builder() .put("hibernate.connection.url", dbConnectionString) .put("hibernate.connection.user", dbUser) .put("hibernate.connection.password", dbPassword) .put("hibernate.c3p0.min_size", minDbConnections) .put("hibernate.c3p0.max_size", maxDbConnections) .put("hibernate.c3p0.timeout", connectionTimeout) .put("hibernate.c3p0.preferredTestQuery", "/* ping */ SELECT 1") .put("hibernate.connection.Charset", "utf8") .put("hibernate.connection.characterEncoding", "utf8") .put("hibernate.connection.useUnicode", "true");
if (connectionTestOnCheckout) { properties.put("hibernate.c3p0.testConnectionOnCheckout", "true"); } else { if (connectionTestOnCheckin) { properties.put("hibernate.c3p0.testConnectionOnCheckin", "true"); } properties.put("hibernate.c3p0.idle_test_period", dbIdleCheckInterval); }
entityManagerFactory = Persistence.createEntityManagerFactory(persistenceUnitName, properties.build()); {code}
We use the javax.persistence @Entity annotations to represent our object being stored int the db. And we have a version attribute with the @Version annotation
{code:java} import java.util.UUID;
import javax.persistence. CascadeType; import javax.persistence. Column; import javax.persistence.Convert; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; import javax.persistence.Version;
@Entity @Table(name = "obj", schema = "schema") public class MyObject {
public MyObject() { }
@Id @Column(name = "id") @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id;
@Version @Column(name = "version") private Long version;
public Long getId() { return id; }
public MyObject setId(Long id) { this.id = id; return this; }
public Long getVersion() { return version; }
public MyObject setVersion(Long version) { this.version = version; return this; } } {code}
* We use the LockModeType.WRITE on some of our JPAQueries to force an update to the version object when needed. however since the hibernate update, entityManager.clear() is clearing the version updates, so the version is not updated ever*
{code:java} MyObj myObj = new MyObj().setVersion(1L); EntityManager em = entityManagerFactory.createEntityManager(); em.getTransaction().begin(); em.persist(myObj); em.getTransaction().commit(); em.close(); MyTransaction transaction = new MyTransaction(entityManagerFactory.createEntityManager()); transaction.incrementVersion(myObj.getId); transaction.commit(); {code}
{code:java} mport import javax.persistence.EntityManager; import javax.persistence.FlushModeType; import javax.persistence.LockModeType; import javax.persistence.RollbackException;
import com.querydsl.jpa.impl.JPAQuery; import com.querydsl.jpa.impl.JPAQueryFactory;
public class MyTransaction{
private final EntityManager entityManager; private final JPAQueryFactory queryFactory;
public MyTransaction(EntityManager entityManager) { this.entityManager = entityManager this.queryFactory = new JPAQueryFactory(entityManager); entityManager.setFlushMode(FlushModeType.COMMIT); entityManager.getTransaction().begin(); }
public void commit() { //Detaches all JPA managed entities, so that only our explicit updates are persisted. version should still be automatically updated via QueryDSL. entityManager.clear(); try { entityManager.getTransaction().commit(); } catch (RollbackException e) { throw e; } }
public void incrementVersion(Long id) { //QMyObj is a Querydsl query type for MyObj JPAQuery<MyObj> query = queryFactory.selectFrom(QMyObj.myObj) .where(QMyObj.myObj.id.eq(id)); query.setLockMode(LockModeType.WRITE); query.fetchOne(); }
public void close() { try { if (entityManager.isJoinedToTransaction()) { entityManager.getTransaction().rollback(); } } finally { entityManager.close(); } } {code}
|
|