10

I am using Hibernate 4.1 trying to call a PreInsertEventListener to update the entity before inserting it into the database, based on the article here: http://anshuiitk.blogspot.ca/2010/11/hibernate-pre-database-opertaion-event.html

public class PreInsertListener implements PreInsertEventListener {

    @Override
    public boolean onPreInsert(PreInsertEvent event) {
        Product product  = (Product)event.getEntity();
        String barcode = "B" + product.getProductId();
        product.setBarcode(barcode);

        // Update the state value that will be persisted
        String[] properties = event.getPersister().getEntityMetamodel().getPropertyNames();
        List<String> propertiesList = Arrays.asList(properties);
        event.getState()[propertiesList.indexOf('barcode')] = barcode;
    }
}

When I debug it, it is executing the PreInsertListener code, but the values inserted into the database do not contain the changes from the code. This used to work in Hibernate 3. What am I missing here?

clarinet
  • 113
  • 1
  • 9
  • 2
    This is the only place that I could find on the whole interwebs that documents the need to update the event.getState object, and not just the entity, when changing a field. Thanks! – Max Mumford Apr 04 '17 at 15:00

3 Answers3

8

Just make sure that you are not falling into the approach-3 problem listed on the blog post that you shared above. If you have insert and update actions on your entity in one single transaction, then your preInsert listener actions will be overridden by the update action.

-- Message from the blog post ( http://anshuiitk.blogspot.ca/2010/11/hibernate-pre-database-opertaion-event.html)

Hibernate generates a prepared statement and fills in the parameters from the 'state' array present in the event. Hence any changes made to the this 'state' array are reflected in the sql statement generated by the hibernate and finally on the database. The insert and update events have a different copy of this states array.

The pre insert listener is called before the pre update event (if an insert as well as update happens). This happens when an entity is created, persisted and then modified in the same transaction. This will result into two seperate sql statements, first will be an insert statement and second one will be an update statement, on the same entity. With the insert statement as we set only the insertUser and insertTime in our PreInsertEventListener and not updateUser and updateTime. The generated statement will look like

insert into entity (id, .... , insert_user, insert_time, update_user, update_time) values (1, .... 'test', '21.11.2010 16:10:00', null, null)

with the PreUpdateEventListener the update SQL generated will be like

update entity set id=1 .... , insert_user=null, insert_time=null, update_user='test', update_time='21.11.2010 16:10:00'
naXa stands with Ukraine
  • 35,493
  • 19
  • 190
  • 259
Santhosh Gandhe
  • 6,900
  • 2
  • 23
  • 17
0

Use the saveorupdate event listener instead.

  • Note that, contrary to Hibernate 3.x behavior, you have to register a SaveOrUpdateEventListener to fire on save, update, OR saveOrUpdate in order to use it for all three cases. – Luke Maurer Aug 18 '14 at 23:34
0

The event listeners themselves have a return value. What this return value does is tell NHibernate whether to execute the actual insert/update SQL queries. When you return false, it executes them. When you return true, it does not. This way you can suppress the actual persistence to the database.

add a return false