现在的位置: 首页 > 综合 > 正文

使用hibernate模拟触发器&拦截器方式

2017年08月21日 ⁄ 综合 ⁄ 共 7989字 ⁄ 字号 评论关闭

在项目中对于事件进行记录是很普遍的事情,比如保存一个实体类(manager.save(entity);其本质为一条insert语句),其实现方式大致有两种方向:1在每个manager层中触发事件时记录的话(缺点:比较难以扩展和维护,耦合性高)  2、触发器方式 (优点:耦合性小 缺点:1、存储过程调试,书写都比较麻烦  2、不同数据库不可相互移植)

我们的方式是使用hibernate提供的拦截器Interceptor模拟触发器:

注:拦截器和过滤器有什么区别?拦截器是面向切面编程的,就是在你的service或者一个方法前调用一个方法,或者在方法后调用一个方法。但是过滤器是在java web中,为你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法url(不是login.do的地址请求,如果用户没有登陆都过滤掉),或者在传入servlet或者 strutsaction前统一设置字符集,或者去除掉一些非法字符)

首先实现一个拦截器NjuptInterceptor.java,定义保存实体和修改实体时的拦截器:

package com.njupt.interceptor;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Iterator;

import org.hibernate.CallbackException;
import org.hibernate.EntityMode;
import org.hibernate.Interceptor;
import org.hibernate.Transaction;
import org.hibernate.type.Type;

import com.njupt.utils.ApplicationContextHolder;
/*
 *事件操作的历史记录:使用拦截器进行处理,而不是用触发器方式
 *原因:1 触发器对于不同数据库写法不同,移植性太差
 *      2 在事件记录中,我们需要记录的不仅仅是事件本身而已,我们还需要记录:事件的操作者,事件的类型,当前用户类型等等信息
 *        这些会导致sql的重新查询等等
 * */
public class NjuptInterceptor implements Interceptor {

	/*  保存时记录事件   */
	public boolean onSave(Object obj, Serializable arg1, Object[] arg2,
			String[] arg3, Type[] arg4) throws CallbackException {
		String modelName = obj.getClass().getSimpleName();
		/* 具体调用的函数名称  */
		String methodName = EventRecord.getCommonPrefix() + modelName + EventRecord.getSaveSuffixes();
		getEventRecordMethod(methodName, obj);
		return false;
	}
	
	/* 修改时记录事件  */
	public boolean onFlushDirty(Object obj, Serializable arg1, Object[] arg2,
			Object[] arg3, String[] arg4, Type[] arg5) throws CallbackException {
		String modelName = obj.getClass().getSimpleName();
		/* 具体调用的函数名称  */
		String methodName = EventRecord.getCommonPrefix() + modelName + EventRecord.getUpdateSuffixes();
		getEventRecordMethod(methodName, obj);
		return false;
	}

	/* 根据反射机制执行相应的函数  */
	public void getEventRecordMethod(String methodName, Object obj) {
		try {
	           Method method = EventRecord.class.getMethod(methodName, Object.class);  
	           method.invoke((EventRecord)ApplicationContextHolder.getBean("eventRecord"), obj); 	
	         } 
		      catch (Exception e) {  System.out.println("Method:"+methodName+ " (from Interceptor)");  }
	}

	@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 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 void postFlush(Iterator arg0) throws CallbackException {
		// TODO Auto-generated method stub

	}

	@Override
	public void preFlush(Iterator arg0) 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
		
	}

}

然后定义一个事件记录类EventRecord.java,其方法定义规则为recordFor +实体名+触发方式 ,比如recordForCompanyUnitSave,就是在执行实体类CompanyUnit执行保存时触发运行:

package com.njupt.interceptor;

import java.util.Date;

import com.njupt.dao.Constants;
import com.njupt.model.ClientUnit;
import com.njupt.model.CompanyUnit;
import com.njupt.model.RecordModule;
import com.njupt.model.RecordPayment;
import com.njupt.model.Role;
import com.njupt.webapp.action.BaseAction;
/**
 * 继承自BaseAction, PS: 该实例并未进行依赖注入,但已在Application.xml进行配置
 * */
@SuppressWarnings("serial")
public class EventRecord extends BaseAction{
	
	private static String prefixPackageName = "com.njupt.model."; // 包的前缀,反射得到类时使用
	// 调用函数的前缀,反射执行函数时使用
	private static String CommonPrefix = "recordFor";
	// 调用函数的后缀,反射执行函数时使用
	private static String SaveSuffixes = "Save";
	private static String DeleteSuffixes = "Delete";
	private static String UpdateSuffixes = "Update";
	private static String QuerySuffixes = "Query";
	
	/* 新添一个公司触发器  */
	public void recordForCompanyUnitSave(Object cu) {
		CompanyUnit temp = (CompanyUnit)cu;
		RecordModule rm = new RecordModule();
		rm.setOperateType(getCurrentUserType());
		rm.setOperateUserId(getCurrentUserId());
        rm.setOperateDate(new java.sql.Timestamp((new Date()).getTime()));
		rm.setOperateType(Constants.SAVE_TYPE_NAME);
		rm.setOperateEntity("CompanyUnit");
		rm.setModuleId(Constants.CompanyUnitBaseInfo_Create);  
		rm.setDescription("增加一个新公司:"+temp.getCompanyName());
		manager.save(rm);
	}
	
	/* 新添一个角色触发器  */
	public void recordForRoleSave(Object cu) {
		Role role = (Role)cu;
		RecordModule rm = new RecordModule();
		rm.setOperateType(getCurrentUserType());
		rm.setOperateUserId(getCurrentUserId());
        rm.setOperateDate(new java.sql.Timestamp((new Date()).getTime()));
		rm.setOperateType(Constants.SAVE_TYPE_NAME);
		rm.setOperateEntity("Role");
		rm.setDescription("增加一个新角色:"+role.getRoleName());
		manager.save(rm);
	}
	/* 修改一个角色触发器  */
	public void recordForRoleUpdate(Object cu) {
		Role role = (Role)cu;
		RecordModule rm = new RecordModule();
		rm.setOperateType(getCurrentUserType());
		rm.setOperateUserId(getCurrentUserId());
        rm.setOperateDate(new java.sql.Timestamp((new Date()).getTime()));
		rm.setOperateType(Constants.UPDATE_TYPE_NAME);
		rm.setOperateEntity("Role");
		rm.setDescription("修改角色:"+role.getRoleName());
		manager.save(rm);
	}
	
	/* 新添一个客户单位触发器  */
	public void recordForClientUnitSave(Object cu) {
		ClientUnit temp = (ClientUnit)cu;
		RecordModule rm = new RecordModule();
		rm.setOperateType(getCurrentUserType());
		rm.setOperateUserId(getCurrentUserId());
        rm.setOperateDate(new java.sql.Timestamp((new Date()).getTime()));
		rm.setOperateType(Constants.SAVE_TYPE_NAME);
		rm.setOperateEntity("ClietnUnit");
		rm.setModuleId(Constants.ClientUnitBaseInfo_Create); 
		rm.setDescription("增加一个新客户:"+temp.getClientUnitName());
		manager.save(rm);
	}
	
	

	public static String getPrefixPackageName() {
		return prefixPackageName;
	}

	public static void setPrefixPackageName(String prefixPackageName) {
		EventRecord.prefixPackageName = prefixPackageName;
	}

	public static String getCommonPrefix() {
		return CommonPrefix;
	}

	public static void setCommonPrefix(String commonPrefix) {
		CommonPrefix = commonPrefix;
	}

	public static String getSaveSuffixes() {
		return SaveSuffixes;
	}

	public static void setSaveSuffixes(String saveSuffixes) {
		SaveSuffixes = saveSuffixes;
	}

	public static String getDeleteSuffixes() {
		return DeleteSuffixes;
	}

	public static void setDeleteSuffixes(String deleteSuffixes) {
		DeleteSuffixes = deleteSuffixes;
	}

	public static String getUpdateSuffixes() {
		return UpdateSuffixes;
	}

	public static void setUpdateSuffixes(String updateSuffixes) {
		UpdateSuffixes = updateSuffixes;
	}

	public static String getQuerySuffixes() {
		return QuerySuffixes;
	}

	public static void setQuerySuffixes(String querySuffixes) {
		QuerySuffixes = querySuffixes;
	}

}

ApplicationContextHolder.java 

package com.njupt.utils;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/*
 * 进行对象实例化
 * */
public class ApplicationContextHolder {
   
	public static ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");  
	
	public static Object getBean(String beanName){  return ac.getBean(beanName);  }
	
}

applicationContext.xml 配置如下:

<bean id="eventRecord" class="com.njupt.interceptor.EventRecord">
        <property name="manager" ref="manager"/>
    </bean>
    <bean id="njuptInterceptor" class="com.njupt.interceptor.NjuptInterceptor" />
<property name="entityInterceptor"><ref bean="njuptInterceptor"/></property> 


还可以参看:http://www.iteye.com/topic/310493

抱歉!评论已关闭.