-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: Hibernate and data level auditing
PostPosted: Mon Jul 31, 2006 12:05 am 
Beginner
Beginner

Joined: Thu May 27, 2004 3:07 pm
Posts: 20
Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp

Hibernate version:
3.2cr2


I have a question about some advanced hibernate usage. Assume my application has the following table:

create table FOO (
FOO_ID BIGINT PRIMARY KEY,
BAR VARCHAR(255),
VERSION BIGINT
);

My application will read/write from this table. However,
I need to keep a detailed history of the changes, so I need
this table as well:

create table FOO_HISTORY (
EVENT_TYPE VARCHAR(6),
EVENT_TIMESTAMP TIMESTAMP,
EVENT_USER VARCHAR(50),
FOO_ID BIGINT,
BAR VARCHAR(255),
VERSION BIGINT
);


I want a record in FOO_HISTORY every time a change is
made to the FOO table. However, the EVENT_USER can
only come from the application, as we use a single userid
within the application to connect to the database (a standard
practice).

If I ADD the EVENT_USER column to the FOO table, I can easily
record INSERT and UPDATE events to the FOO_HISTORY table
though the use of triggers. However, DELETE events cannot
be properly recorded, as there is no EVENT_USER available
for a DELETE event.

So, what I wanted to do was to use hibernate to do all of the
history creation for me. First thing that i noticed was doing this
with an Interceptor does not seem possible, So I looked at the
PreInsert, PreUpdate, and PreDelete events. It also seems impossible
from there as well, since you can't get the right Mapping information
to insert your data appropriately. It seems what I need is the
PersistentClass object. So i created some EntityPersistor classes
(which subclass the 3 existing ones), which can do the data insertions
that I want. This has the drawback of having to set the perisister for
every mapping, but we can deal with that.

However, the problem I run into now is how to deal with collections.
I see that there are some CollectionPersister implementations, which i could extend and write the history tables for those collections.
But, I don't see any way to actually set the CollectionPersistor from the mapping file. The PersisterFactory will pay attention to that property on the Collection object, but there seems no way to set it.

Does anyone have any ideas on how to accomplish this?
Would it be possible to have a pluggable PersisterFactory, so that
an application can supply it's own default persisters?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 31, 2006 1:29 am 
Newbie

Joined: Sat Jul 29, 2006 4:51 am
Posts: 11
mattinger,

From the DB Code you have provided the PreInsert, PreUpdate, and PreDelete events would work fine to accomplish your goals.

Allow me to illustrate,

Assume you have mapped your FOO_HISTORY table to the class named FooHistory and the FOO table to the class Foo.

Code:

class MyEventSync implements PreInsertEventListener, PreUpdateEventListener, PreDeleteEventListener {

public MyEventSync()
{
}

public boolean onPreInsert(PreInsertEvent e)
{
   
   Object entity = e.getEntity();
   
   if (entity instanceof Foo)
   {
      Foo myFoo = (Foo)entity;
      //Now insert code to add an appropiate entry to the FOO_HISTORY Table
   }
   else if (entity instanceof Collection)
   {
     Collection col = (Collection)entity;
     handleCollectionInsert(col);
   }

   return true;
}

public boolean onPreUpdate(PreUpdateEvent e)
{
Object entity = e.getEntity();
   
   if (entity instanceof Foo)
   {
      Foo myFoo = (Foo)entity;
      //Now insert code to add an appropiate entry to the FOO_HISTORY Table
   }
   else if (entity instanceof Collection)
   {
     Collection col = (Collection)entity;
     handleCollectionUpdate(col);
   }

   return true;
}

public boolean onPreDelete(PreDeleteEvent e)
{
Object entity = e.getEntity();
   
   if (entity instanceof Foo)
   {
      Foo myFoo = (Foo)entity;
      //Now insert code to add an appropiate entry to the FOO_HISTORY Table
   }
   else if (entity instanceof Collection)
   {
     Collection col = (Collection)entity;
     handleCollectionDelete(col);
   }

   return true;
}

protected void handleCollectionInsert(Collection c)
{
    Iterator iter = c.iterator();

    while (iter.hasNext())
    {
       Object obj = iter.next();

       if (obj instanceof Foo)
       {
          Foo myFoo = (Foo)obj;
          //Now insert code to add an appropiate entry to the FOO_HISTORY Table
       }
    }
}

protected void handleCollectionUpdate(Collection c)
{
Iterator iter = c.iterator();

    while (iter.hasNext())
    {
       Object obj = iter.next();

       if (obj instanceof Foo)
       {
          Foo myFoo = (Foo)obj;
          //Now insert code to add an appropiate entry to the FOO_HISTORY Table
       }
    }
}

protected void handleCollectionDelete(Collection c)
{
Iterator iter = c.iterator();

    while (iter.hasNext())
    {
       Object obj = iter.next();

       if (obj instanceof Foo)
       {
          Foo myFoo = (Foo)obj;
          //Now insert code to add an appropiate entry to the FOO_HISTORY Table
       }
    }
}

}


That's the basic way to access the object that is about to be inserted into, updated, or deleted from the database. Of course you will need some way to access your application specific code and session. (i.e. via singletons, etc).

I hope this helps.

-----------------

Nathan Klick
CCNA, CCAI, MCSE: Security, AAS in Network Technology


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.