首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

对象批改日志

2012-08-22 
对象修改日志转自:http://hi.baidu.com/419848854/blog/item/4aef20de4464785a95ee37de.html1.对于金融业

对象修改日志
转自:http://hi.baidu.com/419848854/blog/item/4aef20de4464785a95ee37de.html

1.对于金融业务系统中,我们常常需要记录当前用户修改了哪张表中的哪个字段以及修改前的值和修改后的值,对于业务要求较高的公司是非常必须的,这里我主要讲解以下我自己的解决方案:
我所用的框架为SPRING2+Struts2+IBATIS,主要选用IBATIS而不选用HIBERNATE的原因:方便优化SQL ,开发人员上手容易,SQL配置方便,主要还是和更新明细日志记录解决方案相照应。
前期准备工作:
1.对于要记录更新明细日志的IBATIS操作,IBATIS传入的参数必须为Java Bean,如

<statement id="updateRkItemTotal"   parametername="code">/*** @author: zhengjianbo/Ram* @Email: zhengjianbo2@hotmail.com* @Company: DataDriver?2010/www.datadriver.com.cn* @Action: 类注解接口* @DATE: 2010-9-14-上午07:47:46*/@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface BeanAnnotation{/*** 类信息说明,主要保存该Bean对应的表名** @return 注解信息*/public String msg();/*** 编辑保存日志时需要获取原有数据进行比较** @return 通过返回的ibatis statement获取原有数据*/public String ps();/*** @return 返回表格*/public String table();}



Bean类元素注解



/*** @author: zhengjianbo/Ram* @Email: zhengjianbo2@hotmail.com* @Company: DataDriver?2010/www.datadriver.com.cn* @Action: Bean元素注解接口* @DATE: 2010-9-14-上午07:53:10*/@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.FIELD)public @interface FieldAnnotation{/*** 主要用于说明元素对应的字段属性名** @return 元素注解说明*/public String name();/*** @return 返回字段名*/public String column();}


现在比如我想对一个项目名称的更新操作记录详细的日志,则需要做以下工作:

首先,对于需要传入的JavaBean参数加入注解信息:

/*** @author: zhengjianbo/Ram* @Email:zhengjianbo2@hotmail.com* @Company:DataDriver* @Action: 指标总表实体* @DATE: 2010-4-3-上午03:43:25*/@BeanAnnotation(msg="指标总表", table="S_BASEINFO", ps="common.getRkItemTotalToLog")public class RkItemTotal implements java.io.Serializable{@FieldAnnotation(name="指标编码", column="ITCODE")private String itcode;@FieldAnnotation(name="指标简称", column="ITSHORTNAME")private String itshortname;private String orderstr;// 升降序字段 主要用于判断升序还是降序@FieldAnnotation(name="基金代码", column="FCODE")private String fcode;private long sid;//id唯一标识符private long fcodel;private int actiontype; // 操作类型,只当需要记录日志的时候才使用,如果需要记录日志则该Bean必须要有该元素


其中主要需要填写的为:ps(该参数需要填写对应的IBATIS xml文件中的statement id 通过该ID,传入该Bean实体(该Bean为修改好后要传给IBATIS的参数,但其中的某个主键元素可以在PS的statement中获取该数据未修改前的状态)即可获得原有数据)如:
<statement id="getRkItemTotalLog"    parameter --注意:如果其中只有一个参数可以使用java.lang.Long也可以为com.datadriver.risk.po.RkItemTotal,如果有超过一个参数值,则必须为Java Beanresultname="code">/*** 更新数据 包括删除添加修改 并保存操作记录以及详细步骤到数据库** @param obj statement节点配置的parameterClass参数实体* @param action xml文件中的statement的id**/void updateAttributeByPoJo(Object obj, String action){getSqlMapClientTemplate().update(action, obj);// 执行操作}


在service层中根据实际业务需求调用不同操作方法:
/*** @param obj 参数实体*/void updateRkItemTotal(RkItemTotal obj){commonDao.updateAttributeByPoJo(obj, "common.updateRkItemTotal");}



有于我们的增删改统一走一个方法,这样就方便我们对所有操作类型扩展,虽然不可能扩展所有,但可以则中,如我们在Java Bean 加入的actiontype元素,我们可以在Dao方法中通过反射的方式获取Java bean中的该元素值:通过扩展updateAttributeByPoJo方法
     public void updateAttributeByPoJo(Object obj, String action){int actionFlag=0;if(obj!=null){actionFlag=AnnotationUpdateType.getAction(obj);}else{actionFlag=0;}DataDriverLog.log.info("actionFlag:"+actionFlag);先通过反射获取actiontype元素的值,然后根据用户设定给Bean的值来区别操作,如下/** 更新操作,只适用于更新单独的数据 */if(actionFlag==Configer.UPDATE){//annotationLog=new AnnotationUpdateLogImpl();// annotationLog.log(getSqlMapClientTemplate(), obj); 这里用于保存更新记录的详细日志,如保存修改了表S_BASEINFO的S_TYPE字段,将内容从1 改为了2.getSqlMapClientTemplate().update(action, obj);// 执行操作return;}


具体根据obj(要更新的 JavaBean)来查找更新前的数据来和该Bean进行比较,主要通过反射机制获取Bean 以及元素信息,然后通过注解方式获取需要的字段信息,表信息以及ps(获取未更新前的数据的IBATIS statementID),然后再进行比较。。。主要类如下:

/*** @author: zhengjianbo/Ram* @Email: zhengjianbo2@hotmail.com* @Company: DataDriver?2010/www.datadriver.com.cn* @Action: 用于保存类注解,实体类数据(反射获取)等元素信息* @DATE: 2010-9-25-上午09:48:05*/public class AnnotationDataer{private Object t;private Field[] fields;// 实体类元素数组private Fielder[] fielders;// 实体private Class clazz;// 当前实体类public Fielder[] getFielders(){this.fields=this.getFieldByObj();this.fielders=new Fielder[this.fields.length];for(int i=0; i<fields.length; i++){this.fielders[i]=new Fielder();this.fielders[i].setField(fields[i]);this.fielders[i].setFieldname(this.fields[i].getName());this.fielders[i].setObj(this.getFieldData(fields[i]));}return fielders;}public Field[] getFieldByObj(){return t.getClass().getDeclaredFields();// 获得属性}/*** @param field 元素* @return 获取该元素的值* @throws Exception 抛出异常*/public Object getFieldData(Field field){return this.getFieldDataByName(field.getName());}/*** @param fieldName 元素名称* @return 获取元素值*/public Object getFieldDataByName(String fieldName){try{PropertyDescriptor pd=new PropertyDescriptor(fieldName, this.getClazz());Method getMethod=pd.getReadMethod();// 获得get方法Object o=getMethod.invoke(t);// 执行get方法返回一个ObjectDataDriverLog.log.debug("参数"+fieldName+"获取值:"+o+",值类型:");return o;}catch(Exception e){e.printStackTrace();return null;}}/*** @return 获取实体类注解*/public BeanAnnotation getBeanAnnotation(){return t.getClass().getAnnotation(BeanAnnotation.class);}public Object getT(){return t;}public void setT(Object t){this.t=t;}public Field[] getFields(){return fields;}public void setFields(Field[] fields){this.fields=fields;}public Class getClazz(){clazz=this.getT().getClass();return clazz;}public void setClazz(Class clazz){this.clazz=clazz;}public void setFielders(Fielder[] fielders){this.fielders=fielders;}}public void log(SqlMapClientTemplate template, Object obj){List<Loger> logList=new ArrayList<Loger>();AnnotationDataer annotationDataer=new AnnotationDataer();annotationDataer.setT(obj);BeanAnnotation beanAnnotation=annotationDataer.getBeanAnnotation();String table=beanAnnotation.table();// 表名Object oldObj=template.queryForObject(beanAnnotation.ps(), obj);// 获取数据AnnotationDataer oldAnnotationDataer=new AnnotationDataer();oldAnnotationDataer.setT(oldObj);Fielder[] fielders=annotationDataer.getFielders();/****************************************** 遍历要修改的数据****************************************/for(Fielder fielder : fielders){String fieldname=fielder.getFieldname();// 字段名称(元素名称)FieldAnnotation fieldAnnotation=fielder.getFieldAnnotation(fielder.getField());Object dataObj=fielder.getObj();if(fieldAnnotation!=null){Object oldDataObj=oldAnnotationDataer.getFieldDataByName(fieldname);// 原始数据/** 更新数据时才记录* */if(dataObj!=null){if(!(dataObj+"").equals(oldDataObj+"")){Loger loger=new Loger();loger.setTable(table);loger.setColumn(fieldAnnotation.column());loger.setSold(oldDataObj+"");loger.setSnew(dataObj+"");// loger.setTuser(UserSession.get("").toString());logList.add(loger);}}}}

热点排行