BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News Hibernate 4.1 Released With Improved Auditing Support

Hibernate 4.1 Released With Improved Auditing Support

Leia em Português

This item in japanese

Bookmarks

Less than 2 months after Hibernate 4.0, JBoss has already released version 4.1 of Hibernate, the open source Object/Relational (O/R) mapping framework. Whilst this minor update includes several fixes and improvements, there is also a very interesting new feature in the audit module of Hibernate (previously known as Envers).

A common requirement in enterprise applications is the storage of historical database data. The database keeps previous versions of the data for reference purposes so that past decisions can be re-created by looking at the respective version of data. In security sensitive organizations, database auditing is also a strict requirement. At any point in time one should be able to read a "backlog" and understand all transitions of a database table up to its current state (along with the respective user that performed each change).

This requirement can, of course, be implemented with custom in-house code. An example solution would entail having a second table that keeps all transitions for each database table that needs to be audited. Therefore the first table keeps only the current state of the data, while the helper table keeps all intermediate states with some additional metadata (i.e. a timestamp and the user that initiated the change). This implementation requires all existing code that affects the database to be changed into a two step process, where the first step is saving the previous state into the history table and the second step is the actual change as before. It also means that all new code must be implemented following this principle, making the solution very code intrusive.

The Hibernate Envers module solves this problem in a transparent manner. The guiding principle of having an additional history table for each audited Entity still holds but all history management is automatically handled by Envers behind the scenes in an automatic way. The application code is mostly unchanged (assuming that Hibernate Annotations are already used). Envers functions in a manner similar to Subversion, meaning that each change creates a new global revision in the database.

Envers comes with its own API that allows for querying the database under a specific revision in the past instead of looking at the current state. Envers was integrated in Hibernate core in version 3.6 (and has been lately included in JBoss Application Server as well), so all the described functionality so far was already available in Hibernate 4.0

New in Hibernate 4.1 is the ability for tracking changes in individual Entity properties. Consider a scenario where the present state of an audited property is incorrect or suspicious and the user of the application wants to find the version where the last change happened for this specific property. Currently the API of Envers can be used to retrieve a previous revision of the object and then a diff is needed to determine if this revision was also responsible for this change. But with the new hasChanged() method of the AuditProperty class the exact revision(s) can be pinpointed directly.

For more information see the updated Javadocs.

Rate this Article

Adoption
Style

Hello stranger!

You need to Register an InfoQ account or or login to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Community comments

  • Not completely safe

    by Anthony Shaughnessy,

    • Re: Not completely safe

      by Ronald Miura,

      • Re: Not completely safe

        by Anthony Shaughnessy,

        • Re: Not completely safe

          by Mac Noodle,

          • Re: Not completely safe

            by Michael Burke,

            • Re: Not completely safe

              by Roopesh Shenoy,

            • Re: Not completely safe

              by Mac Noodle,

              • Not completely safe

                by Anthony Shaughnessy,

                Your message is awaiting moderation. Thank you for participating in the discussion.

                I haven't used Envers and I'm sure it has soom very cool features but it assumes all clients of the database are using the same Hibernate layer. This is not true often enough that it is difficult to rely on. The more traditional database trigger approach ensures that auditing is in place regardless of the application-layer technology being used by the different applications accessing the database. Performance is likely to be better as well. If you are confident that all access to the database will be via this layer now and in the future then I can see this being nicer than triggers but I'm not swayed by the portability argument. You're as likely to swap out hibernate as you are to swap database vendor.
                Anthony

              • Re: Not completely safe

                by Ronald Miura,

                Your message is awaiting moderation. Thank you for participating in the discussion.

                Well, I'm neither a db nor envers expert, but I agree that database triggers are probably safer and easier to maintain than something like envers.

                But I also think that envers can do some things that may not be that easy to implement with triggers. For example, to 'query the past' probably is easier (more transparent, maybe not simpler) with envers.

                Logging the current user may also be a challenge with triggers, since we usually use a shared connection pool instead of one connection per user (like in the old Delphi days), and the current user is only available in application scope (probably in the HTTP Session), not in database scope (which uses a single database user for all application requests).

              • Re: Not completely safe

                by Anthony Shaughnessy,

                Your message is awaiting moderation. Thank you for participating in the discussion.

                Absolutely agree Ronald - logging the "who" that made a change is difficult with triggers. That's why I said there are probably lots of cool things that Envers can do, this was one of them. That makes it tricky to choose between the two approaches. I wouldn't like to say that either is correct, but I'd start with the general principle of "can other technology stacks access this database" - if this will ever be allowed, then stick with triggers. Otherwise Envers might be better.
                Anthony

              • Re: Not completely safe

                by Mac Noodle,

                Your message is awaiting moderation. Thank you for participating in the discussion.

                Saying "databases are not switched out" and then doing thing to make it near impossible, is basically a "self fulfilling prophesy". If you bypass layers, you will have more issues than just auditing. You have to deal with duplicate business logic, tight coupling (all must change together), "who is locking the database", caching, etc. SOA has been around for quite a while, and it still puzzles me as to how many people don't get the principles.

                When developers use an ORM (and keep ALL code out of the DB engine), they are more likely to use something like H2 to develop with and run Unit/Integration tests with, rather than something like Oracle/DB2/SQL Server, MySQL. About 7 years ago, we were easily able to switch from Sybase/Linux to DB2/ZOS because we used Hibernate and didn't treat the DB like an app server. In fact, we had to rename tables/fields because of required naming conventions. And it still only took a very short time.

                While triggers are "more safe", they are NOT easier to maintain. Typically, you must have a DBA involved, at least for production.

                Another thing to consider is deploying your apps to "the cloud". Typically, when deploying, you pick a db as service. In this scenario, Envers would be much better than triggers.

                What happens you put caching or a grid between your "app" and the database?

                If you bypass layers, using something like this is difficult - www.jasypt.org/hibernate.html#
                Of course, use Jasypt might be useful to ensure people DON'T bypass layers.

              • Re: Not completely safe

                by Michael Burke,

                Your message is awaiting moderation. Thank you for participating in the discussion.

                I think everyone understands the principle of controlling access to a database as much possible. In my experience however, it is more of an ideal than a realistic policy.

                The reality of any non-trivial application in a non-perfect world is that you will want to be able to change something in the database without having to call in Java developers to craft the necessary code.

                Prime example: data fixes to address a problem introduced by a code bug in a past release (or a user error). You can spend a lot of time and money writing Java code to effect the fix, or you can just write a SQL script to fix it and be done with it, assuming your referential integrity is turned on. Either way, an audit trail is still necessary to understand where a change came from.

                In this world, any application worth talking about is going to have a DBA behind it anyway; regardless, the developers would be expected to be component in whatever flavour of SQL the system is running on. Perhaps this is a different world to what others may be working in.

                Personally, I think Envers is great as long as it can coexist with triggers populating the same audit trail table independently. I'm assuming that's the case. It addresses an important, generally ignored issue in the Java persistence space and I applaud it for doing that!

                YMMV

              • Re: Not completely safe

                by Roopesh Shenoy,

                Your message is awaiting moderation. Thank you for participating in the discussion.

                any application worth talking about is going to have a DBA behind it anyway


                That's a huge assumption. If you are selling an installable product for a small business, don't expect it to be baby sitted by a DBA. And just because the target is smaller businesses doesn't mean the application is not worth talking about.

                IF your application needs datafixes too often, then something's wrong. And if its once in a while, just add the auditing data in the datafix itself. I don't have any specific views on whether your triggers should be in the database or in your java code, (to me that's immaterial as long as your app works fine), but saying that presence of a DBA is a good reason for database triggers is not something I would agree with.

              • Re: Not completely safe

                by Mac Noodle,

                Your message is awaiting moderation. Thank you for participating in the discussion.

                The reality in non-trivial apps (aka Enterprise Apps) is that Grids, Caches, Full Text Indexes (i.e. Lucene), Polyglot persistence and/or Message queues are being used. That makes it difficult if not impossible to modify the Relational Database Directly via SQL. We do not live in a RDMBDS heliocentric world anymore.

                In my experience, many times it easier to use Java (Groovy, whatever JVM language) or just HQL to fix problems rather than use raw SQL, even when the above are not involved. Sometimes, yes, SQL is simpler. But even then, the person writing the SQL has to understand the overall system architecture and the implications and having just someone who knows SQL make the changes is ... less than optimal.

                "In this world, any application worth talking about is going to have a DBA behind it anyway". Not true. Databases have gotten much better and need less (if any) DBA assistance (see, for reference, DB2 Magazine a few quarters ago). In addition, PaaS is pretty much based on the fact that the DB is just another service you choose when deploying an app.
                We have a VERY large app and all our DBAs do is backup/restore and deploy our DDL to prod (because we don't have access). And that is only for the DBs we don't control.

                "Personally, I think Envers is great as long as it can coexist with triggers populating the same audit trail table independently. I'm assuming that's the case. It addresses an important, generally ignored issue in the Java persistence space and I applaud it for doing that!"
                The trigger code to create all that Envers does will not be trivial and will be custom for each app created. Additionally, you will end up with duplicate code that you will have to keep in sync.

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

BT