利用反射比较并记录对象修改的值
前述
这几天项目有一个需求,就是在更新采购申请表信息时,需要记录更新了哪些字段的信息。如果字段少的话倒还好,两个新旧对象循环去比较就行了,但是字段很多的情况就不适用了,而且后续也可能还会有这样的需求,所以应该整一个通用的比较工具类去实现。
我们知道,可以通过getDeclaredField
来获取一个实例的字段,通过Field
的get()
方法可以获取到对应字段在实例中的数据,这样我们就可以通过反射封装一个工具类,来比较新旧两个对象相同字段不同的值的记录了。
代码示例
新增注解
/**
* 用于比较并记录相同对象相同属性的不同值
*
* @author LiJunYi
* @date 2022/08/17
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ForUpdate
{
/**
* 字段名
*
* @return {@link String}
*/
String fieldName() default "";
/**
* int转换str
* 0 否 1是
* @return boolean
*/
boolean intConvertStr() default false;
/**
* 是否从缓存中读取
*
* @return boolean
*/
boolean readFromCache() default false;
/**
* 从哪个缓存读取
*
* @return {@link ReadFromCacheType}
*/
ReadFromCacheType readFromCacheType() default ReadFromCacheType.NONE;
}
ReadFromCacheType枚举
/**
* @version 1.0.0
* @className: ReadFromCacheType
* @description: 从指定缓存中获取数据
* @see InitialLoadSomeMap#initialSomeMap()
* @author: LiJunYi
* @create: 2022/8/17 13:48
*/
public enum ReadFromCacheType
{
/**
* 缓存数据
*/
CONTRACT_TYPE_REASON_MAP,
/**
* 缓存数据
*/
PRICING_MODE_MAP,
/**
* 缓存数据
*/
SECRET_POINT_MAP,
/**
* 没有
*/
NONE
}
实体类添加注解
@Data
public class CgModel implements Serializable {
private static final long serialVersionUID=1L;
@ForUpdate(fieldName = "合同类型")
private String contractType;
@ForUpdate(fieldName = "合同类型理由", readFromCache = true , readFromCacheType = ReadFromCacheType.CONTRACT_TYPE_REASON_MAP)
private String contractTypeReasonId;
// .......
}
工具类
/**
* @version 1.0.0
* @className: BeanUpdateUtils
* @description: 通过反射比较并记录对象相同属性字段新旧值对比
* @author: LiJunYi
* @create: 2022/8/17 9:28
*/
@Slf4j
public class BeanUpdateUtils
{
/**
* 返回新旧值结果
*
* @param newBean 新对象
* @param oldBean 旧对象
* @return {@link String}
*/
public static <T> String getChangedFields(T newBean, T oldBean)
{
// 获取属性
Field[] fields = newBean.getClass().getDeclaredFields();
StringBuilder builder = new StringBuilder();
for(Field field : fields)
{
field.setAccessible(true);
if (field.isAnnotationPresent(ForUpdate.class))
{
try
{
Object newValue = Optional.ofNullable(field.get(newBean)).orElse("");
Object oldValue = Optional.ofNullable(field.get(oldBean)).orElse("");
if(!Objects.equals(newValue, oldValue))
{
builder.append("将 【");
builder.append(field.getAnnotation(ForUpdate.class).fieldName());
builder.append("】 由 【");
builder.append(oldValue);
builder.append("】 修改为 【");
builder.append(newValue);
builder.append("】;\n");
}
} catch (Exception e)
{
log.error("记录采购申请单修改记录异常,异常原因:{}",e.getMessage());
}
}
}
return builder.toString();
}
}