需求:用户修改某一实体后,系统记录下用户修改了哪些内容
原方法:采取笨方法,取数据库中的老数据与新数据进行一一遍历比较
缺点:费时,代码量也较大
现方法:利用自定义注解以及反射相结合的方法,自动获取实体的属性以及注释,并比较新旧数据,返回修改内容
优点:缩减了代码量,尤其是属性很多的实体
自定义注解类
/**
* 实体bean类字段描述 自定义注解
* @author liu huangming
* @date 2020-03-03 15:20:03
*/
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.FIELD})// 次注解作用于类和字段上
public @interface FieldAnnotation {
String desc();
}
实体
/**
* 示例实体
* @package: com.bean.smLayout
* @author: liu huangming
* @date: 2020年4月20日 下午5:31:34
*/
public class UserInfo implements Serializable{
private static final long serialVersionUID = 1L;
private Integer id;
@FieldAnnotation(desc = "用户名")
private String userName;
@FieldAnnotation(desc = "联系方式")
private String phone;
@FieldAnnotation(desc = "性别")
private Integer sex;
@FieldAnnotation(desc = "年龄")
private Integer age;
@FieldAnnotation(desc = "地址")
private String address;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Integer getSex() {
return sex;
}
public void setSex(Integer sex) {
this.sex = sex;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
解析方法
private static final String EDIT_TECHINFO_TEMPLATE = " 由 %s 修改为 %s";
/**
* 获取用户修改内容
* @author: liu huangming
* @date: 2020年4月20日 下午5:41:08
* @param oldData 数据库中的老数据实体
* @param newData 新修改后的数据实体
* @param changeMap 用于返回用户修改的属性以及对应修改的内容
*/
public void getChangeInfo(Object oldData,Object newData,Map<String, Object> changeMap) {
try {
// 获取该实体所有属性
Field[] fields = oldData.getClass().getDeclaredFields();
for (Field field : fields) {
if(field.getName().equals("serialVersionUID") || field.getName().equals("id")) {
continue;
}
// 根据属性名获取其get方法
PropertyDescriptor pd = new PropertyDescriptor(field.getName(), oldData.getClass());
Method method = pd.getReadMethod();
// 调用get方法获取值,这里也可以直接使用field.get(oldData),field.get(newData)获取属性的值
String preContent = method.invoke(oldData) != null ? method.invoke(preObject).toString() : "";
String currContent = method.invoke(newData) != null ? method.invoke(object).toString() : "";
// 记录下当前数据的ID
if(!preContent.equals(currContent)){
// 检索字段上是否有注解
boolean fieldHasAnno = field.isAnnotationPresent(FieldAnnotation.class);
if(fieldHasAnno) {
FieldAnnotation annotation = field.getAnnotation(FieldAnnotation.class);
// 获取字段上的注解
String descString = annotation.desc();
changeMap.put(descString+":",String.format(EDIT_TECHINFO_TEMPLATE,method.invoke(oldData),method.invoke(newData) ));
}
}
}
} catch (IntrospectionException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
public String updateUserInfo(UserInfo userInfo) {
Map<String, Object> changeMap = new HashMap<>();
UserInfo oldData = userDao.getUserInfoById(userInfo.getId());
getChangeInfo(oldData, userInfo, changeMap);
for(Map.Entry<String, Object> entry : changeMap.entrySet()){
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
return SUCCESS;
}