Interceptor拦截器的使用小结,程序实例是典型的 “数据稽核”过程,即在对数据库中的数据进行修改后会自动添加对应的日志记录在数据库中对应的日志表中,用于记录对数据库中关键数据的修改过程和追踪,最重要的应用主要是日志记录功能,将业务层的逻辑处理和数据访问层的处理分离开来。功能类似于spring 中的aop功能。
Pojo类代码:Tuser类
package com.inspur.po;
import java.util.HashSet;
import java.util.Set;
/**
* TUser entity. @author MyEclipse Persistence Tools
*/
public class TUser implements java.io.Serializable {
// Fields
private Integer id;
private String name;
private Integer age;
private Set TAddresses = new HashSet(0);
// Constructors
/** default constructor */
public TUser() {
}
/** full constructor */
public TUser(String name, Integer age, Set TAddresses) {
this.name = name;
this.age = age;
this.TAddresses = TAddresses;
}
// Property accessors
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
public Set getTAddresses() {
return this.TAddresses;
}
public void setTAddresses(Set TAddresses) {
this.TAddresses = TAddresses;
}
}
Taddress类代码:
package com.inspur.po;
/**
* TAddress entity. @author MyEclipse Persistence Tools
*/
public class TAddress implements java.io.Serializable {
// Fields
private Integer id;
private TUser TUser;
private String address;
private String zipcode;
private String street;
// Constructors
/** default constructor */
public TAddress() {
}
/** full constructor */
public TAddress(TUser TUser, String address, String zipcode, String street) {
this.TUser = TUser;
this.address = address;
this.zipcode = zipcode;
this.street = street;
}
// Property accessors
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public TUser getTUser() {
return this.TUser;
}
public void setTUser(TUser TUser) {
this.TUser = TUser;
}
public String getAddress() {
return this.address;
}
public void setAddress(String address) {
this.address = address;
}
public String getZipcode() {
return this.zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
public String getStreet() {
return this.street;
}
public void setStreet(String street) {
this.street = street;
}
}
Tauditlog类代码:
package com.inspur.po;
/**
* TAuditlog entity. @author MyEclipse Persistence Tools
*/
public class TAuditlog implements java.io.Serializable {
// Fields
private Integer id;
private String user;
private String action;
private String entityname;
private String commit;
private Integer actiontflag;
// Constructors
/** default constructor */
public TAuditlog() {
}
/** full constructor */
public TAuditlog(String user, String action, String entityname,
String commit, Integer actiontflag) {
this.user = user;
this.action = action;
this.entityname = entityname;
this.commit = commit;
this.actiontflag = actiontflag;
}
// Property accessors
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUser() {
return this.user;
}
public void setUser(String user) {
this.user = user;
}
public String getAction() {
return this.action;
}
public void setAction(String action) {
this.action = action;
}
public String getEntityname() {
return this.entityname;
}
public void setEntityname(String entityname) {
this.entityname = entityname;
}
public String getCommit() {
return this.commit;
}
public void setCommit(String commit) {
this.commit = commit;
}
public Integer getActiontflag() {
return this.actiontflag;
}
public void setActiontflag(Integer actiontflag) {
this.actiontflag = actiontflag;
}
}
日志记录类代码:
package com.inspur.dao;
import java.sql.Connection;
import java.util.Iterator;
import java.util.Set;
import org.hibernate.CallbackException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import com.inspur.po.TAuditlog;
import com.inspur.po.TUser;
public class AuditLogDaoImpl {
public static void doLog(String action,String userId,Set modifyset,Connection connection){
Configuration config=new Configuration().configure();
SessionFactory sessionFactory=config.buildSessionFactory();
//重用interceptor中的session的jdbc Connection创建临时session
Session session=sessionFactory.openSession(connection);
Iterator it=modifyset.iterator();
TAuditlog auditLog=new TAuditlog();
TUser user=null;
try{
while(it.hasNext()){
user=(TUser)it.next();
auditLog.setAction(action);
auditLog.setCommit(user.getName());
auditLog.setUser(userId);
auditLog.setActiontflag(user.getId());
//此次不用开启transaction的原因就是临时session重用了当前session的jdbc connection,而
//外围已经开启了当前session的 jdbc connection
session.save(auditLog);
//此次的临时session是不关联到拦截器的,所以不会触发拦截器中的 postflush方法。
session.flush();
}
}catch(Exception e){
throw new CallbackException(e);
}finally{
try{
if(session!=null){
session.close();
}
}catch(Exception e1){
throw new CallbackException(e1);
}
}
}
}
拦截器类代码:
package com.inspur.interceptor;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.hibernate.CallbackException;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.type.Type;
import com.inspur.dao.AuditLogDaoImpl;
import com.inspur.po.TUser;
public class MyInterceptor implements Interceptor{
private Session session;
private String userId;
private Set insertSet=new HashSet();
private Set updateSet=new HashSet();
public Session getSession() {
return session;
}
public void setSession(Session session) {
this.session = session;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public Set getInsertSet() {
return insertSet;
}
public void setInsertSet(Set insertSet) {
this.insertSet = insertSet;
}
public Set getUpdateSet() {
return updateSet;
}
public void setUpdateSet(Set updateSet) {
this.updateSet = updateSet;
}
@Override
public void afterTransactionBegin(Transaction arg0) {
// TODO Auto-generated method stub
}
@Override
public void afterTransactionCompletion(Transaction arg0) {
// TODO Auto-generated method stub
}
@Override
public void beforeTransactionCompletion(Transaction arg0) {
// TODO Auto-generated method stub
}
@Override
public int[] findDirty(Object arg0, Serializable arg1, Object[] arg2,
Object[] arg3, String[] arg4, Type[] arg5) {
// TODO Auto-generated method stub
return null;
}
@Override
public Object getEntity(String arg0, Serializable arg1)
throws CallbackException {
// TODO Auto-generated method stub
return null;
}
@Override
public String getEntityName(Object arg0) throws CallbackException {
// TODO Auto-generated method stub
return null;
}
@Override
public Object instantiate(String arg0, EntityMode arg1, Serializable arg2)
throws CallbackException {
// TODO Auto-generated method stub
return null;
}
@Override
public Boolean isTransient(Object arg0) {
// TODO Auto-generated method stub
return null;
}
@Override
public void onCollectionRecreate(Object arg0, Serializable arg1)
throws CallbackException {
// TODO Auto-generated method stub
}
@Override
public void onCollectionRemove(Object arg0, Serializable arg1)
throws CallbackException {
// TODO Auto-generated method stub
}
@Override
public void onCollectionUpdate(Object arg0, Serializable arg1)
throws CallbackException {
// TODO Auto-generated method stub
}
@Override
public void onDelete(Object arg0, Serializable arg1, Object[] arg2,
String[] arg3, Type[] arg4) throws CallbackException {
// TODO Auto-generated method stub
}
@Override
public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState,
Object[]previousState , String[] propertyNames, Type[] types) throws CallbackException {
if(entity instanceof TUser){
updateSet.add(entity);
}
return false;
}
@Override
public boolean onLoad(Object arg0, Serializable arg1, Object[] arg2,
String[] arg3, Type[] arg4) throws CallbackException {
// TODO Auto-generated method stub
return false;
}
@Override
public String onPrepareStatement(String arg0) {
// TODO Auto-generated method stub
return arg0;
}
@Override
public boolean onSave(Object entity, Serializable id, Object[] state,
String[] propertyNames, Type[] types) throws CallbackException {
if(entity instanceof TUser){
insertSet.add(entity);
}
return false;
}
/*
* 所有的sql都执行完成以后,即事物的提交完成以后再执行一次postflush方法,不与session的动作相关联
* 而是作为整个session生命周期结束的最终执行方法*/
@Override
public void postFlush(Iterator entity) throws CallbackException {
try{
if(insertSet.size()>0){
AuditLogDaoImpl.doLog("insert", userId, insertSet, session.connection());
System.out.println(insertSet.size());
}
if(updateSet.size()>0){
AuditLogDaoImpl.doLog("update", userId, updateSet, session.connection());
}
}catch(HibernateException e){
e.printStackTrace();
}
}
@Override
public void preFlush(Iterator arg0) throws CallbackException {
// TODO Auto-generated method stub
}
}
Test类代码如下:
package com.inspur.test;
import java.util.List;
import org.hibernate.HibernateException;
/*
* 程序的总体执行过程是:利用当前session的jdbc connection创建一个临时的session用于将日志实体对象
* 保存到数据库中,在临时session中不需要开启和关闭事物,因为当前session的jdbc connection已经在
* 之前开启了,重用connection可以是一个事物只占用一个数据库连接,提供数据访问性能,在interceptor中
* 是不能调用当前session的,因为interceptor中的所有方法都是由当前session负责调用的,如果在方法中调用
* 当前session进行数据持久化操作,将导致session内部状态混乱。*/
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import com.inspur.interceptor.MyInterceptor;
import com.inspur.po.TUser;
import junit.framework.TestCase;
public class InterceptorTest extends TestCase {
Session session=null;
@Override
protected void setUp() throws Exception {
Configuration config=new Configuration().configure();
SessionFactory sessionFactory=config.buildSessionFactory();
MyInterceptor interceptor_cus=new MyInterceptor();
session=sessionFactory.openSession(interceptor_cus);
interceptor_cus.setSession(session);
interceptor_cus.setUserId("current user");
}
@Override
protected void tearDown() throws Exception {
// session.close();
}
public void testInterceptor(){
TUser user=new TUser();
user.setName("uuu_sky");
Transaction tran=null;
try{
tran=session.beginTransaction();
session.save(user);
//如果此处使用session.flush()方法那么实际上是调用了两次dolog方法,在对应的日志数据库中会
//插入两条记录,因为tran.commit()实际上包含了执行一次session.flush方法
// session.flush();
tran.commit();
}catch(HibernateException e){
e.printStackTrace();
tran.rollback();
}finally {
if(session!=null){
session.close();
}
}
}
public void testUpdate(){
String hql="from TUser user where user.name=? ";
Query query=session.createQuery(hql);
query.setString(0, "uuu_sky");
List list=query.list();
TUser user=(TUser)list.get(0);
System.out.println(user.getName());
user.setName("liuzhiqiang");
Transaction tran=session.beginTransaction();
try{
session.update(user);
tran.commit();
}catch(HibernateException e){
e.printStackTrace();
tran.rollback();
}finally{
if(session!=null){
try{
session.close();
}catch(HibernateException e){
e.printStackTrace();
}
}
}
}
}
最终的执行效果是向数据库中插入数据 和修改数据库中的现有数据都会将每次操作记录进数据库日志表中,保存当前操作的日志记录。