Search code examples
javahibernatejpabulk

Bulkupdate Cache issue? Hibernate / IntegrationTest / Inmemory DB /


For my Integration tests I am using a HSQLDB-Inmemory.

When i execute a bulk update via jql query I am not able to get the updated results afterwards.

Entity.class

@Entity
public class Entity {
   private Long id;
   private String someCriteria;
   private Boolean changed = Boolean.FALSE;

   @Id
   @Column (name = "ID")
   public Long getId() {
      return id;
   }

   @Column (name = "SOMECRITERIA")
   public String getSomeCriteria() {
      return someCriteria;
   }

   @Column (name = "CHANGED")
   @Type (type = "yes_no")
   public String isChanged() {
      return changed;
   }

   […]
}

DataStore.class […]

@Transactional
updateChangedMethod() {
Query query = entityManager.get().createQuery(“UPDATE Entity e SET e.changed = true WHERE (d.someCriteria = ‘true’) ");
query.executeUpdate();
}

@Transactional
selectAllMethod() {
Query query = entityManager.get().createQuery("Select e from Entity e", Entity.class);
}
[…]

Service.class

 execute(){
        updateChangedMethod() ;
        selectAllMethod(); // Results do not contain the update
    }

When I execute a refresh for each entity explicitly the select works as expected:

 @Transactional
    refresh(){
    Query query = entityManager.get().createQuery("Select e from Entity e",  Entity.class);
    List<Entity> result = query.getResultList();

    for (Entity entity : result) {
        entityManager.get().refresh(entity);
    }
    }


   execute(){
            updateChangedMethod() ;
            refresh();
            selectAllMethod(); // Results do contain the update
      }

I am using Hibernate v 5.1.0.Final and HSQLDB v 2.3.4. I assume that this is a Cache issue, is there a way to receive the expected results directly without calling a refresh on each entity?


Solution

  • The persistence context is not updated to reflect the results of the bulk operation. Bulk operations are issued as SQL against the database, bypassing the in-memory structures of the persistence context.

    You have three ways to achieve the up-to-date result from entity manager:

    • refresh the entity
    • evict all the cache in entity manager and force it to update everything from beginning
    • Making the bulk operations work in their own transactions by adding @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) to method signature. (I'm not sure how it will be implemented in spring, may be @Transactional(propagation = Propagation.REQUIRES_NEW))