Hibernate - Envers -> auditing / versioning of an attribute, but only if the value changed

StackOverflow https://stackoverflow.com/questions/4602684

  •  25-09-2019
  •  | 
  •  

Question

I have a problem with Hibernate - Envers. I have a domain object with only one audited attribute status which can be one of the numbers 0,1,2,3,4,5.

@Entity
public class Item {
    ...
    @Audited
    private int status;
    ... other variables, setter/getter, ...
}

Now, everything in Envers and Hibernate is working. Creating a new Item object and add it to the database a row is inserted into theItem_AUD database table.

But now I have a problem with updating it. My update in the Hibernate Dao implementation looks like:

public void updateItem(Item i) {
    SessionFactory sessionFac = HibernateUtility.getSessionFactory();
    Session s = sessionFac.getCurrentSession();
    Transaction trans = s.beginTransaction();
    s.update(i);
    s.flush();
    trans.commit();
}

On every update, this is printed on my console:

Hibernate: update Item set amount=?, description=?, status=? where id=?
Hibernate: insert into REVINFO (REVTSTMP) values (?)
Hibernate: insert into Item_AUD (REVTYPE, status, id, REV) values (?, ?, ?, ?)

But the problem is, that I only want to insert a row into the REVINFO and Item_AUD if the status number has changed!

For example: I change the description of the item, perform the update with calling updateItem and then Envers write a new revision to the auditing tables. But I do not want this behavior.

What I want: only if the value of status is changed, Envers should write database entries into the auditing tables.

But how can I do this?

Best Regards, Tim.

Was it helpful?

Solution

For this, you have to extend AuditEventListener & override its methods.

    public class EnversListener extends AuditEventListener {

      @Override
      public void onPostInsert(PostInsertEvent event) {

        Object o = event.getEntity();

        if (o instanceof Item) {

          Item currentItem = (Item) o;
          Item previousItem = findItemById(currentItem.getId());

          if(previousItem != null)
              if (currentItem.getStatus() != previousItem.getStatus()) 
                 super.onPostInsert(event);

        } else {
          super.onPostInsert(event);
        }
      }

      @Override
      public void onPostDelete(PostDeleteEvent event) {
        super.onPostDelete(event);
      }

      @Override
      public void onPostRecreateCollection(PostCollectionRecreateEvent event) {
        super.onPostRecreateCollection(event);
      }

      @Override
      public void onPostUpdate(PostUpdateEvent event) {
          super.onPostUpdate(event);
      }

      @Override
      public void onPreRemoveCollection(PreCollectionRemoveEvent event) {
        super.onPreRemoveCollection(event);
      }

      @Override
      public void onPreUpdateCollection(PreCollectionUpdateEvent event) {
        super.onPreUpdateCollection(event);
      }
}

You can add custom constraints in the other overridden methods as required. The path to the listener class inside hibernate.cfg.xml should be configured accordingly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top