说明:本例在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