4.实体的属性名不好记,想加一个好记别名,这样便于查询.
使用步骤和上次基本一样,但在实体上需要加入注解:
1.得到变化前后的对象.
2.调用下面方法传入第一步中的值.
HistoryUtil util = new HistoryUtil();
util.record(类名, 变化前的对象, 变化后的对象,修改人);
实体类及属性上的注解:
package com.tgb.lk.history2; public class Person { @HistoryId //标识Id private int id; @HistoryAlias(alias = "姓名") //加入别名 private String name; @HistoryAlias(alias = "性别") //加入别名 private String sex; @HistoryNotRecord //设置即使属性发生变化也不记录历史 private String clazz; //get和set方法略 @Override public String toString() { return "Person [clazz=" + clazz + ", id=" + id + ", name=" + name + ", sex=" + sex + "]"; } }测试例子:
package com.tgb.lk.history2; public class HistoryTest { public static void main(String[] args) { Person s = new Person(); s.setId(1); s.setName("李坤"); s.setSex("1");// 1代表"男" s.setClazz("五期提高班"); // 可以使用commons-beanutils-xxx.jar中的这个方法来保留原对象. // BeanUtils.copyProperties(dest, src); Person s2 = new Person(); s2.setId(1); s2.setName("李佳"); s2.setSex("0");// 0代表"女" HistoryUtil util = new HistoryUtil(); util.record(Person.class, s, s2, "admin"); } }
核心代码:
注解:
(1)HistoryId
package com.tgb.lk.history2; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target( { java.lang.annotation.ElementType.FIELD }) public @interface HistoryId { }(2)HistoryAlias:
package com.tgb.lk.history2; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target( { java.lang.annotation.ElementType.FIELD }) public @interface HistoryAlias { public abstract String alias(); }(3)HistoryNotRecord:
package com.tgb.lk.history2; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target( { java.lang.annotation.ElementType.FIELD }) public @interface HistoryNotRecord { }HistoryUtil<T>:
package com.tgb.lk.history2; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; /* * @author likun * 记录属性变更历史的工具类,使用步骤见main方法. * HistoryUtil util = new HistoryUtil(); * util.record(Person.class, s, s2, "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); Map<String, String> sexMap = new HashMap<String, String>(); sexMap.put("1", "男"); sexMap.put("0", "女"); for (History history : historys) { if (history.getEntity().equals("class com.tgb.lk.history2.Person")) { // 处理sex字段值中含义不明确的0,1变为含义明确的"男","女" if (history.getProperty().equals("sex")) { history.setOldValue(sexMap.get(history.getOldValue())); history.setNewValue(sexMap.get(history.getNewValue())); } // 其他逻辑的处理..... } } System.out.println("处理后的记录:" + historys); // 调用批量添加入库方法. } /** * 比较两个对象哪些属性发生变化,将变化的属性保存为History对象. 实体中用@HistoryId注解的自动保存到实体类的Id字段中. * 实体中有@HistoryAlias的注解自动解析为指定的别名. * * @param clazz * 修改类 * @param oldObj * 老对象 * @param newObj * 新对象 * @param user * 修改人 */ public void record(Class<T> clazz, T oldObj, T newObj, String user) { if (oldObj == newObj) { return;// 如果两个对象相同直接退出 } List<History> list = new ArrayList<History>(); Field[] fields = clazz.getDeclaredFields();// 得到指定类的所有属性Field. List<Field> allFields = new ArrayList<Field>(); Field idField = null; // 找出Id字段,便于记录 for (Field field : fields) { field.setAccessible(true);// 设置类的私有字段属性可访问. if (field.isAnnotationPresent(HistoryId.class)) { idField = field; } // 设置了不记录变化的注解字段不记录变更历史. if (!field.isAnnotationPresent(HistoryNotRecord.class)) { allFields.add(field); } } // 比较实体对象的属性值,每个属性值不同的都新建一个History对象并保存入库. for (Field field : allFields) { field.setAccessible(true);// 设置类的私有字段属性可访问. field.getAnnotation(HistoryAlias.class); try { // ^是异或运算符 if ((field.get(oldObj) != null ^ field.get(newObj) != null) || (!field.get(oldObj).equals(field.get(newObj)))) { History history = new History(); history.setEntity(clazz.toString()); history.setProperty(field.getName()); if (field.isAnnotationPresent(HistoryAlias.class)) { history.setAlias(field .getAnnotation(HistoryAlias.class).alias()); } history.setOldValue(String.valueOf(field.get(oldObj))); history.setNewValue(String.valueOf(field.get(newObj))); history.setModifyDate(new Date()); if (idField != null) { history .setEntityId(String .valueOf(idField.get(oldObj)));// 记录修改的对象的主键Id. } history.setUser(user);// 记录修改者 list.add(history); } } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } record(list);// 调用保存入库的方法. } }
实体属性变更历史记录框架(一)-变更历史记录从此无忧(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