In this post I am talking about auditing for the business, not the technical infrastructure.  As an example story, users will want to see certain fields highlighted on a grid if that field has changed in the last week, and the info about the change (who, when, what) should be a tooltip for the cell.

Database trigger

NH Interceptor (per NH in action and the NH docs)

NH Listener (per the Hibernate docs)

Domain model

Because auditing is a simple application of interceptors there is a lot of guidance online about that approach, and using an interceptor was my first attempt at auditing.

But since the concept of an audit entry is important to the application (and the users!), it makes sense to promote this concept to a domain object.  Reporting is simple and the behavior is easier to manage.  Create a class called AuditEntry (with supporting mapping file) and hang collections of AuditEntry from the entity. Manage this collection in regular behavior:

public virtual void ChangeStatus(Employee employee, DateTime time, OrderStatus status)
{
    if(this.Status != status)
    {
        AuditEntry entry = new AuditEntry(employee, time, this.Status, status);
        _auditEntries.Add(entry);
    }
    Status = status;
}

After having gone down the database trigger path and the interceptor path and encountering friction I now recommend the domain model approach.