Rydell
Rydell

Reputation: 4217

Generation of Create_Date and Update_Date columns using Hibernate

I'm using straight Hibernate 3.0 without annotations.

When saving or updating domain objects, I would like to have Hibernate automatically generate the CREATE_DT and UPDATE_DT fields, as opposed to using database triggers.

What are the best practices for accomplishing this?

The background is that I have an object graph being passed from a client, that contains multiple objects. Some of which will end up being inserted and others updated. I could set the dates on the client, but this would be a bad idea. Setting the dates on the server means I would have to rifle through the graph and detect the changes.

It seems to me that Hibernate would have a facility for making this happen, but it is not jumping out at me.

Upvotes: 2

Views: 653

Answers (3)

Rydell
Rydell

Reputation: 4217

I'm checking Pascal's answer as the correct answer as he pointed me directly to the point in the documentation that provided detail and example code. But for the reader, I'm adding more detail here.

I tried both the hibernate events as well as the interceptors, and found that an interceptor worked better in my situation. It was relatively easy to implement.

Thanks for the help!

Below is the code for the interceptor:

public class AuditInterceptor extends EmptyInterceptor {

    private Log log = LogFactory.getLog(this.getClass());

    private int updates;
    private int creates;

    @Override
    public boolean onSave(Object entity, Serializable id, Object[] state,
            String[] propertyNames, Type[] types) {
        if (entity instanceof AuditableVO) {
            creates++;
            // Find the create date and change it
            for (int i=0; i < propertyNames.length; i++) {
                if (propertyNames[i].equals("createDate")) {
                    state[i] = new Date();
                    return true;
                }
            }
        }
        return false;
    }
    @Override
    public boolean onFlushDirty(Object entity, Serializable id,
            Object[] currentState, Object[] previousState,
            String[] propertyNames, Type[] types) {
        if (entity instanceof AuditableVO) {
            updates++;
            // Find the update date and change it
            for (int i=0; i < propertyNames.length; i++) {
                if (propertyNames[i].equals("updateDate")) {
                    currentState[i] = new Date();
                    return true;
                }
            }           
        }
        return false;
    }
    @Override
    public void afterTransactionCompletion(Transaction tx) {
        if (tx.wasCommitted()) {
            log.info("Creations: " + creates + ", Updates: " + updates);
        }
        creates = 0;
        updates = 0; 

        super.afterTransactionCompletion(tx);
    }
}

Upvotes: 0

Will Marcouiller
Will Marcouiller

Reputation: 24152

The simplest way according to me to achieve this would be to have those fields as properties into your object class and set them privately through your constructor. When a property value would be changed, set your DateUpdated (for instance) to DateTime.Now (or whatever it may be in Java).

Once your entity is being persisted, it would automatically save those dates and persist them to your underlying database.

It is not directly with Hibernate, but I would consider this solution easier to implement than playing with Interceptors.

Hope this helps!

Upvotes: 0

Pascal Thivent
Pascal Thivent

Reputation: 570615

The Hibernate way to do this without using triggers would be to use Hibernate's event architecture and to register listeners for PreInsertEvent, PreUpdateEvent or SaveOrUpdateEvent (have a look at the org.hibernate.event package for a full list) to set and update the create/update dates.

Another option would be to use an interceptor, either Session-scoped or SessionFactory-scoped, to set the create and update dates in onSave(...) and the update date in onFlushDirty(...).

Maybe have a look at this previous answer for other options.

Upvotes: 1

Related Questions