在实际mis项目中增删改查必不可少,针对"改"的操作,重要的项目中都要有变更历史记录.本实例提供了一个实体属性变更历史记录工具类,只要写很少的代码就能实现强大的变更历史记录功能.本工具类的主要优点是1.工具类对实体对象没有依赖性,任何对象都能记录历史.
先看看如何使用吧:
1.得到变化前后的对象.
2.调用下面方法传入第一步中的值.
HistoryUtil util = new HistoryUtil();
util.record(类名, 变化前的对象, 变化后的对象,实体Id,修改人);
例子详细代码:
package com.tgb.lk.history; public class HistoryTest { public static void main(String[] args) { Student s = new Student(); s.setId(1); s.setName("李坤"); s.setSex("男"); s.setClazz("五期提高班"); // 可以使用commons-beanutils-xxx.jar中的下面这个方法来保留原对象. // BeanUtils.copyProperties(dest, src); Student s2 = new Student(); s2.setId(1); s2.setName("李佳"); s2.setSex("女"); // HistoryUtil util = new HistoryUtil(); // util.record(Student.class, s, s2,"1","admin"); HistoryUtil<Student> util = new HistoryUtil<Student>();//方法内部有输出 util.record(Student.class, s, s2, "1", "admin"); } }
例子输出结果:
实体类:package com.tgb.lk.history; public class Student { private int id; private String name; private String sex; private String clazz; //get和set方法 @Override public String toString() { return "Student [clazz=" + clazz + ", id=" + id + ", name=" + name + ", sex=" + sex + "]"; } }核心逻辑:
package com.tgb.lk.history; import java.util.Date; public class History { private int id; private String entity; // 实体类名,标记是哪个实体类 private String entityId; // 实体对象的Id private String property; // 实体的属性名,标记实体的哪个属性发生修改 private String oldValue; // 原属性值 private String newValue; // 新属性值 private String user; // 修改人 private Date modifyDate; // 修改时间 private String desc; // 描述 //get和set方法略 @Override public String toString() { return "\n History [id=" + id + ", entity=" + entity + ",\n entityId=" + entityId + ", property=" + property + ", oldValue=" + oldValue + ", newValue=" + newValue + ",\n user=" + user + ", modifyDate=" + modifyDate + ", desc=" + desc + "]\n"; } }HistoryUtil类(注意需要修改一下注释中添加入库和批量入库的实现):
package com.tgb.lk.history; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Date; import java.util.List; /* * @author likun * 记录属性变更历史的工具类,使用步骤见main方法. * HistoryUtil util = new HistoryUtil(); * util.record(Student.class, s, s2,"1","admin"); */ public class HistoryUtil<T> { /** * 支持自己定义一个History对象并保存入库. * * @param history */ public void record(History history) { System.out.println(history); // 调用添加入库方法. } // 批量保存到数据库中,考虑到对象修改的属性可能较多,所以采用批量导入效率会高一些. public void record(List<History> historys) { System.out.println(historys); // 调用批量添加入库方法. } /** * 比较两个对象哪些属性发生变化,将变化的属性保存为History对象. * * @param clazz * 修改类 * @param oldObj * 老对象 * @param newObj * 新对象 * @param entityId * 实体Id * @param user * 修改人 */ public void record(Class<T> clazz, T oldObj, T newObj, String entityId, String user) { if (oldObj == newObj) { return;// 如果两个对象相同直接退出 } List<History> list = new ArrayList<History>(); Field[] allFields = clazz.getDeclaredFields();// 得到指定类的所有属性Field. for (Field field : allFields) { field.setAccessible(true);// 设置类的私有字段属性可访问. try { if (!field.get(oldObj).equals(field.get(newObj))) { History history = new History(); history.setEntity(clazz.toString()); history.setProperty(field.getName()); history.setOldValue(String.valueOf(field.get(oldObj))); history.setNewValue(String.valueOf(field.get(newObj))); history.setModifyDate(new Date()); history.setEntityId(entityId);// 记录修改的对象的主键Id. history.setUser(user);// 记录修改者 list.add(history); } } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } record(list);// 调用保存入库的方法. } }
这篇文章中是属性变更历史记录框架的核心逻辑,看看你是否有这样的需求:
1.所有属性都记录变更历史太多,有些属性我不想记录变更历史.
2.实体属性变化前后的值需要把编码转成有意义的文字.例如:实体类中性别用0,1表示,而希望变更历史中记录前后变化的值是"男","女".
3.传入实体对象自动识别实体Id,而不需要手工传入.
4.实体的属性名不好记,想加一个好记别名,这样便于查询.
请看下篇文章:http://blog.csdn.net/lk_blog/article/details/8092925
实体属性变更历史记录框架(一)-变更历史记录从此无忧(http://blog.csdn.net/lk_blog/article/details/8007777)
实体属性变更历史记录框架(二)-变更历史记录从此无忧(http://blog.csdn.net/lk_blog/article/details/8092925)
限于本人水平有限,很多地方写的并不完美,希望大家不吝赐教.如果觉得本文对您有帮助请顶支持一下,如果有不足之处欢迎留言交流,希望在和大家的交流中得到提高.
代码下载:http://download.csdn.net/detail/lk_blog/4667643