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

来源:互联网 发布:天猫品类销售数据 编辑:程序博客网 时间:2024/06/05 15:36

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

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

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

首先实现一个拦截器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)");  }}@Overridepublic void afterTransactionBegin(Transaction arg0) {// TODO Auto-generated method stub}@Overridepublic void afterTransactionCompletion(Transaction arg0) {// TODO Auto-generated method stub}@Overridepublic void beforeTransactionCompletion(Transaction arg0) {// TODO Auto-generated method stub}@Overridepublic int[] findDirty(Object arg0, Serializable arg1, Object[] arg2,Object[] arg3, String[] arg4, Type[] arg5) {// TODO Auto-generated method stubreturn null;}@Overridepublic Object getEntity(String arg0, Serializable arg1)throws CallbackException {// TODO Auto-generated method stubreturn null;}@Overridepublic String getEntityName(Object arg0) throws CallbackException {// TODO Auto-generated method stubreturn null;}@Overridepublic Object instantiate(String arg0, EntityMode arg1, Serializable arg2)throws CallbackException {// TODO Auto-generated method stubreturn null;}@Overridepublic Boolean isTransient(Object arg0) {// TODO Auto-generated method stubreturn null;}@Overridepublic void onCollectionRecreate(Object arg0, Serializable arg1)throws CallbackException {// TODO Auto-generated method stub}@Overridepublic void onCollectionRemove(Object arg0, Serializable arg1)throws CallbackException {// TODO Auto-generated method stub}@Overridepublic void onCollectionUpdate(Object arg0, Serializable arg1)throws CallbackException {// TODO Auto-generated method stub}@Overridepublic boolean onLoad(Object arg0, Serializable arg1, Object[] arg2,String[] arg3, Type[] arg4) throws CallbackException {// TODO Auto-generated method stubreturn false;}@Overridepublic String onPrepareStatement(String arg0) {// TODO Auto-generated method stubreturn arg0;}@Overridepublic void postFlush(Iterator arg0) throws CallbackException {// TODO Auto-generated method stub}@Overridepublic void preFlush(Iterator arg0) throws CallbackException {// TODO Auto-generated method stub}@Overridepublic 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

0 0
原创粉丝点击