5

I have a set of domain objects and its related tables for application's configurations. Authenticated users can change these domain objects data thru a presentation layer. These domain objects have very important data and I need find who and when changed their data. My application's data access layer is implemented using JPA, Hibernate and Spring. I need to have a record of every change, consisting of: User + Action Date + Action Type + previous values.

For example, let's consider a trivial domain object (simplified for the purpose of this question):

@Entity
class Connection
{
   private Long id;
   private String name;
   private String protocol;
}

Assume there is a Connection instance with the following values:

Connection 
    id = 1;
    name = Web;
    protocol = HTTPS;

After a user (eg John) logins in UI and changes this connection to the following values:

Connection
    id = 1;
    name = Web;
    protocol = HTTP;

As you can see, John changes protocol from HTTPS to HTTP (a secure protocol to insecure!), as a result I need to save the history of Connection instances in another table for auditability.

I've researched for a solution for me and found following result:

  1. Trigger: one possibility is to define triggers on the tables, cons of this way is dependency to a database.
  2. Hibernate Envers: this solution is good but makes my DAO layer depend on Hibernate and I won't have the benefit of JPA and its provider independency.
  3. Spring Data Commons + hades: is good but added some column to any entity by MappedSuperClass annotation like: Create User, Create Date, Last Update User and Last Update Date. It means storing the complete history and state of a entity.
  4. My own design/implementation:* I could implement a layer for this goal but I don't like this solution because I think this requirement isn't special for me and I think it's been solved by other people following best practices (I shouldn't reinvent the wheel)

Does anyone have any suggestions or solutions for this problem?

(sorry if my question is long and maybe be too basic for experts)

Daniel Serodio
  • 4,229
  • 5
  • 37
  • 33
Sam
  • 6,770
  • 7
  • 50
  • 91

4 Answers4

1

I've worked with many systems where we add extra columns to the database tables to track user ID and timestamp for audit purposes.

If you need to keep track of the previous values you can use date ranges to tell when the data was valid. For example:

from 01.01.2012 to 31.12.2012 the protocol was HTTPS from 01.01.2013 to 'forever' the protocol was HTTP

For more on patterns of time see Martin Fowler's blog.

SteveD
  • 5,396
  • 24
  • 33
1

If you already use Hibernate: Hibernate Audit/Envers is the best solution.

Look, if you ever want to get rid of Hibernate, you can switch to Solution #1/#4 then.

Daniel Serodio
  • 4,229
  • 5
  • 37
  • 33
Grim
  • 1,938
  • 10
  • 56
  • 123
  • Thanks. I already use `Hibernate Envers` and thinking it's best solution, only I afraid when to decide for change `JPA` provider from `Hibernate` to another, for sample `OpenJPA` or `Toplink`, the day I haven't audit/history of entities :( – Sam Jan 22 '13 at 15:02
0

You can easily use Hibernate Envers to achieve flexible auditing.

There is a small start-up example in my project on GitHub: jpauc-ear. And read official docs with usage examples.

Viacheslav Dobromyslov
  • 3,168
  • 1
  • 33
  • 45
  • 1
    Thanks, I have experience with `Hibernate Envers` but it binds my application to `Hibernate ORM` and I haven't `JPA` provider independent benefit. – Sam Feb 05 '13 at 07:06
  • @MJM JPA purpose is to provide abstraction layer not dependent on DBMS, therefore #1 trigger also does not fit. I would use #3 way. – Viacheslav Dobromyslov Feb 06 '13 at 03:29
  • Yes, you're rigth. My means is aslo : by `Hibernate Envers` I depend to `Hibernate` implementation of `JPA` api and it isn't good. – Sam Feb 06 '13 at 07:05
0

If you don't like coupling with concrete ORM, you can use http://javers.org as it's more versatile and gives support for SQL and NoSql databases

Bartek Walacik
  • 3,386
  • 1
  • 9
  • 14