java 审计日志,利用Hibernate拦截机制生成审计日志

说明:本例在Eclipse3.1中新建一个java项目来进行测试

环境:Eclipse3.1+Oracle 10g+Hibernate2+winXP sp2

1.在Oracle中新建一个用户:

create user work identified by

caecaodb default tablespace users;

grant dba,connect,resource to work;

//用户授权

2.在该用户下新建两个表CUSTOMER,AUDIT_LOGS,sql语句如下:

create table CUSTOMER

(

ID NUMBER

not null,

NAME VARCHAR2(15)

)

tablespace USERS

pctfree 10

initrans 1

maxtrans 255

storage

(

initial

64K

minextents

1

maxextents

unlimited

);

alter table CUSTOMER

add constraint CUSTOMERS_ID primary key

(ID)

using index

tablespace USERS

pctfree 10

initrans 2

maxtrans 255

storage

(

initial

64K

minextents

1

maxextents

unlimited

);

insert into CUSTOMERS (ID, NAME) values (1, 'my_log');

//先新建一条记录在表中,以便进行delete测试时使用.

//新建AUDIT_LOGS

create table AUDIT_LOGS

(

ID NUMBER not null,

ENTITY_ID NUMBER,

ENTITY_CLASS VARCHAR2(128),

MESSAGE VARCHAR2(255),

CREATED DATE

)

tablespace USERS

pctfree 10

initrans 1

maxtrans 255

storage

(

initial

64K

minextents

1

maxextents

unlimited

);

alter table AUDIT_LOGS

add constraint AUDIT_LOGS_ID primary key

(ID)

using index

tablespace USERS

pctfree 10

initrans 2

maxtrans 255

storage

(

initial

64K

minextents

1

maxextents

unlimited

);

3.在Eclipse3.1中新建一个java项目,命名为:HibernateSample,再新建一个源文件夹src,再在src下新建包hibernate.audit和hibernate.cfg.xml

hibernate.cfg.xml的内容如下:

encoding='utf-8'?>

/p>

Configuration DTD//EN"

name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver

name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:orcl

name="hibernate.connection.username">work

name="hibernate.connection.password">caecaodb

name="hibernate.show_sql">true

name="dialect">net.sf.hibernate.dialect.OracleDialect

 

name="hibernate.connection.isloation">2

 

resource="hibernate/audit/Customer.hbm.xml"/>

resource="hibernate/audit/AuditLogRecord.hbm.xml"/>

4.在包hibernate.audit下新建如下内容(附相关说明)

接口: Auditable.java

//是为了在保存日志记录到表AUDIT_LOGS时得到持久类的id.

package

hibernate.audit;

public interface Auditable {

public Long getId();

}

类AuditLogRecord.java

//该类是日志表的持久类

package hibernate.audit;

import java.util.Date;

public class AuditLogRecord {

public Long entityid;

public String message;

public Class entityClass;

public Date created;

public AuditLogRecord(String message, Long

entityid, Class entityClass) {

this.message = message;

this.entityid = entityid;

this.entityClass =

entityClass;

this.created = new

Date();

}

public AuditLogRecord() {

}

}

类:Customer.java

//该类是实体类,实现了接口Auditable.java,Auditable.java主要是为了让Customer类必须有getId()方法,以便在保存日志时能得到实体类的id值

package hibernate.audit;

public class Customer implements Auditable{

Long id;

String

name; public Customer()

{}

public Customer(String name)

{

this.name=name;

}

public Long getId() {

return id;

}

public void setId(Long id) {

this.id = id;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name =

name; } }

类:HibernateUtil.java //用于管理session

package hibernate.audit;

import net.sf.hibernate.*;

import net.sf.hibernate.cfg.Configuration;

public class HibernateUtil {

private static SessionFactory

sessionFactory;

public static final ThreadLocal session= new

ThreadLocal();

static {

try {

//

实例化一个SessionFactory对象 //System.out.println("通过静态模块创建一个SessionFactory");

sessionFactory

= new Configuration().configure()

.buildSessionFactory();

} catch (HibernateException ex)

{

throw new

RuntimeException("Configuration problem:"

+

ex.getMessage(), ex);

}

}

public static Session getSession(Interceptor

interceptor) //将session和拦截器相绑定

throws

HibernateException {

Session tempsession = (Session)

session.get();

if (tempsession == null ||

!tempsession.isOpen()) {

tempsession =

sessionFactory.openSession(interceptor);

session.set(tempsession);

}

return tempsession;

}

public static void closeSession() throws

HibernateException {

Session s = (Session)

session.get();

if (s != null) {

s.close();

}

}

}

类:AutitLog.java //该类完成日志记录的保存

注:因为传入的session的状态不稳定,因此通过它来得到jdbc连接,再通过该jdbc连接来得到一个新的session

package hibernate.audit;

import java.sql.Connection;

import net.sf.hibernate.Session;

import net.sf.hibernate.SessionFactory;

public class AutitLog {

public static void logEvent(String message,

Auditable entity,Session session) {

Session tempSession =

null;

try {

SessionFactory

sessionFactory = session.getSessionFactory();

Connection

conn = session.connection();

tempSession =

sessionFactory.openSession(conn); AuditLogRecord

record=new

AuditLogRecord(message,entity.getId(),entity.getClass()); tempSession.save(record);

tempSession.flush();

} catch (Exception e) {

e.printStackTrace();

} finally {

try {

tempSession.close();

} catch

(Exception e) {

e.printStackTrace();

}

}

}

}

类:AuditLogIntercepor.java //该类实现了拦截器接口,本例只实现了insert,update,delete日志,因此只在这三种数据操作的相关方法中加入了业务逻辑

package hibernate.audit;

import java.io.Serializable;

import java.util.HashSet;

import java.util.Iterator;

import java.util.Set;

import net.sf.hibernate.CallbackException;

import net.sf.hibernate.Interceptor;

import net.sf.hibernate.Session;

import net.sf.hibernate.type.Type;

public class AuditLogIntercepor implements

Interceptor,Serializable {

private static final long serialVersionUID =

1L;

private Session session;

private Set inserts = new HashSet();

private Set updates = new HashSet();

private Set delete = new HashSet();

public void setSession(Session session) {

this.session = session;

}

public boolean onLoad(Object arg0,

Serializable arg1, Object[] arg2,

String[]

arg3, Type[] arg4) throws CallbackException {

// TODO 自动生成方法存根

return false;

}

//当flush()方法检查到脏对象时调用该方法

public boolean onFlushDirty(Object entity,

Serializable id,

Object[]

currentState, Object[] previousState,

String[]

propertyNames, Type[] type) throws CallbackException {

// TODO 自动生成方法存

System.out.println("onFlushDirty()执行,传入的类为:"+entity.getClass());

if (entity instanceof

Auditable) {

updates.add(entity);

}

return false;

}

//保存一个对象之前Hibernate自动调用该方法

public boolean onSave(Object entity, Serializable

arg1, Object[] arg2,

String[]

arg3, Type[] arg4) throws CallbackException {

// TODO 自动生成方法存根

System.out.println("onSave()执行,传入的类为:"+entity.getClass());

if (entity instanceof

Auditable) {

inserts.add(entity);

}

return false;

}

//删除一个对象之前Hibernate自动调用该方法

public void onDelete(Object entity, Serializable

arg1, Object[] arg2,

String[]

arg3, Type[] arg4) throws CallbackException {

// TODO 自动生成方法存根

System.out.println("onDelete()执行,传入的类为:"+entity.getClass());

if (entity instanceof

Auditable) {

delete.add(entity); } }

public void preFlush(Iterator arg0) throws

CallbackException {

// TODO 自动生成方法存根

}

public void postFlush(Iterator entities)

throws CallbackException {

// TODO 自动生成方法存根

try

{ Iterator it =

updates.iterator();

while

(it.hasNext()) {

Auditable

entity = (Auditable) it.next();

AutitLog.logEvent("update",

entity, session);

}

it =

inserts.iterator();

while

(it.hasNext()) {

Auditable

entity = (Auditable) it.next();

AutitLog.logEvent("insert",

entity, session);

}

it =

delete.iterator();

while

(it.hasNext()) {

Auditable

entity = (Auditable) it.next();

AutitLog.logEvent("delete",

entity, session);

}

} catch (Exception e) {

} finally {

inserts.clear();

updates.clear();

delete.clear();

}

}

public Boolean isUnsaved(Object arg0)

{

// TODO 自动生成方法存根

return null;

}

public int[] findDirty(Object arg0,

Serializable arg1, Object[] arg2,

Object[]

arg3, String[] arg4, Type[] arg5) {

// TODO 自动生成方法存根

return null;

}

public Object instantiate(Class arg0,

Serializable arg1)

throws

CallbackException {

// TODO 自动生成方法存根

return null;

}

}

映射文件:AuditLogRecord.hbm.xml //用于完成日志表的日志持久类的映射

/p>

table="audit_logs">

column="ID">

class="increment"/>

 

name="entityid" type="long" column="ENTITY_ID" access="field" not-null="true" />

name="message" type="string" column="MESSAGE" access="field"

not-null="true"/> 

name="entityClass" type="class" column="ENTITY_CLASS" access="field"

not-null="true" /> 

name="created" type="timestamp"

column="CREATED" access="field" not-null="true"/> 

映射文件:Customer.hbm.xml  //用于完成customer类和customer表的映射

/p>

"-//Hibernate/Hibernate Mapping DTD 2.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"

>

table="customer">

column="ID">

class="increment"/>

 

type="string" column="NAME" />

类:HibernateTest.java //含main()方法的入口类

package hibernate.audit;

import net.sf.hibernate.LockMode;

import net.sf.hibernate.Session;

import net.sf.hibernate.Transaction;

public class HibernateTest {

public static void main(String[] args) throws

HibernateException,

SQLException,

IOException {

new

HibernateTest().doit();

}

public void doit() throws HibernateException,

SQLException, IOException {

AuditLogIntercepor interceptor

= new AuditLogIntercepor();

Session session =

HibernateUtil.getSession(interceptor);

//拦截器类AuditLogIntercepor要与session关联才能激发拦截器

interceptor.setSession(session);

Transaction tx =

session.beginTransaction();

Customer customer = new

Customer("test_log");

session.save(customer);//保存时生成日志

customer.setName("my_log");

//更新时生成日志 Customer cs = (Customer)

session.load(Customer.class, new

Long(1),LockMode.UPGRADE);//悲观锁定;id=1的记录,在新建customer表的时候已经建立

session.delete(cs);//删除时生成日志 tx.commit(); session.close();

}

}

最后,将HibernateTest.java以java应用程序方式运行,再看表customer已有一条id=1,name="test_log"的记录;audit_logs表中则有三条日志记录,记录了insert,update,delete

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值