BeforeUpdateEntityListener - how to get the old value before update

In Entity Listener, How can I get the old value before it was modified?
I tried the following code and when debugged, found that the line " oldAmt = list.getQuantity();" returns new value but i was expecting old.


   private void updateBalance(InventoryDeliveryCustD operation) {
        EntityManager em = persistence.getEntityManager();
        TypedQuery<InventoryDeliveryCustD> query = em.createQuery("select e from mydb$InventoryDeliveryCustD e " +
                "where e.id = ?1", InventoryDeliveryCustD.class);
        query.setParameter(1, operation.getId());

        InventoryDeliveryCustD list = query.getFirstResult();
        BigDecimal oldAmt = new BigDecimal(0);
        if(list.getId()!=null){
            oldAmt = list.getQuantity();
        }
        TypedQuery<InventoryBalance> query2 = em.createQuery("select e from mydb$InventoryBalance e " +
                "where e.warehouse.id = ?1 AND e.material.id = ?2", InventoryBalance.class);
        query2.setParameter(1, operation.getInventoryDeliveryCustH().getWarehouse().getId()).setParameter(2, operation.getMaterial().getId());
        List<InventoryBalance> lists = query2.getResultList();

        if(!lists.isEmpty()){
            for (InventoryBalance balance : lists) {
                balance.setBalance(balance.getBalance().add(oldAmt).subtract(operation.getQuantity()));
            }
        }
    }
1 Like

Hi Mortoza,
Let me explain why it works this way.
A Before listener is executed for an open persistence context - an in-memory cache of loaded entity instances which is maintained by an EntityManager instance. The term “Before” means that all these entity instances are not yet stored in the database, but ORM always tries to emulate transparency between instances in persistence context and records in the database. That is why when you call EntityManager.find() for an instance in the persistence context, the in-memory state is returned, not the state in the database. The same is for queries, but the process is more complex: a query cannot be run in memory reliably, so ORM first saves all changed instances to the database and then run the query on DB. So when you run a query in a Before listener, it causes an implicit flush of the persistence context. This is not a problem usually because if something fails onwards, the whole transaction will be rolled back. Anyway, when you execute a query in a transaction, it returns the new state of changed entities.

There are two ways of getting old values in an entity listener:

  • Create a new transaction and execute the query (or invoke EntityManager.find()) in it. This will not cause the flush and you will get the old values from the database.
  • Use persistence.getTools().getOldValue() method. It returns the old value which has been read by ORM without going to the database again, so this way is preferred.

Thank you Konstantin for explanation. I’ll then use the recommended method. I didn’t find a detailed documentation, would you please provide a sample code to use getOldValue() method in this regard?

See JavaDocs on the com.haulmont.cuba.core.PersistenceTools#getOldValue method.
For your case it should be something like:


private void updateBalance(InventoryDeliveryCustD operation) {
    BigDecimal oldAmt = persistence.getTools().getOldValue(operation, "quantity");
    ...

Thank you so much. It worked perfectly.