java获取两个对象不同属性
最近在公司接到一个系统操作日志的开发,完成如下的一个小需求,记录相关人员在系统中的操作记录
目录
最近在公司接到一个系统操作日志的开发,完成如下的一个小需求,记录相关人员在系统中的操作记录
1. 分析
2. 查阅资料
3. 调用牛逼博主的API,说干就干
4. 升级版
1. 分析
首先要完成如上的需求,我们要有一个大致的思路,新增、删除、修改三种操作日志,其中新增前端会上传对象信息,直接生成一条日志的记录,删除操作一般会上传id,根据id查询数据库,拿到你想要的字段。
难点在与修改操作:修改操作类似新增,不过会有该条数据的标识如表id,我们可以根据id去数据库中查询旧值(需要注意的是该操作必须在事务更新前执行,不然查询出来的数据会是新值,坑点),拿到旧值对象,接下来我们只需要对比新旧值之间有哪些字段值不同即可判断,修改了哪些内容。
2. 查阅资料
接到开发任务的我毫不慌张,毕竟网上的资源一大堆,根据自己的需求去问度娘................巴拉巴拉,终于找到一篇文章可以为我所用 Java比较两个对象并获取其中不相等的字段
该篇文章主要讲如何获取两个对象中不相等的字段(前提是类对象相同哈)。。。大家可直接前往参谋.....我这里不再赘述。
API调用工程师终于等到你。。不想看的人直接复制下面的依赖吧。。。
<dependencies><dependency><groupId>com.github.dadiyang</groupId><artifactId>equator</artifactId><version>1.0.3</version></dependency>
3. 调用牛逼博主的API,说干就干
核心接口代码如下:
接口实现继承如下,每个方法该文的博主介绍的很详细,我这里简单说几句:
FieldBaseEquator 抽象类实现,我们主要用到这里类。
一个优秀的程序员,必须要学会 copy 大神的优秀代码,来吧上代码,先编写一个实体User类
public class User {private int age;private String name;private List<String> friendName;public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public List<String> getFriendName() {return friendName;}public void setFriendName(List<String> friendName) {this.friendName = friendName;}}
执行main方法,没有什么问题~
public static void main(String[] args) {User user = new User();user.setAge(25);user.setFriendName(Arrays.asList("chq","tom","Thompson"));user.setName("ChenHQ");User user1 = new User();user1.setAge(28);user1.setFriendName(Arrays.asList("chq2","tom"));user1.setName("ChenHQ");FieldBaseEquator fieldBaseEquator = new FieldBaseEquator();List<FieldInfo> diffFields = fieldBaseEquator.getDiffFields(user, user1);for (FieldInfo diffField : diffFields) {System.out.println(diffField);}}
运行结果如下:
我们可以看到,通过 getDiffFields 方法,我们可以获取到实体类“值”不同的属性
4. 升级版
我们通过博主的构造方法得到,可以指定某些字段进行对比,或者指定某些字段不进行对比,只需要在构造方法中传入属性名称即可
/*** 指定包含或排除某些字段** @param includeFields 包含字段,若为 null 或空集,则不指定* @param excludeFields 排除字段,若为 null 或空集,则不指定*/public FieldBaseEquator(List<String> includeFields, List<String> excludeFields) {super(includeFields, excludeFields);}
来实现一下吧,首先编写一个自定义注解,该注解标识在属性字段上,用来注明是否需要对比的字段
@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public @interface AnnotationDemo {String value() default "";}
我们在 年龄,名字 字段上加上声明的注解 @AnnotationDemo,其他不做修改
public class User {@AnnotationDemo("年龄")private int age;@AnnotationDemo("姓名")private String name;private List<String> friendName;......}
写一个静态方法,返回对象中被注解注释的属性名集合 (即: age,name)
/*** 获取对象注解注释过的属性名集合** @param obj* @return*/private static List<String> getImportFieldName(Object obj) {//创建集合对象,保存是否是重要字段名List<String> importFieldName = new ArrayList<>();//获取类加载器对象Class studentClass = obj.getClass();//获取所有的字段Field[] declaredFields = studentClass.getDeclaredFields();for (Field declaredField : declaredFields) {if (declaredField.isAnnotationPresent(AnnotationDemo.class)) {//保存importFieldName.add(declaredField.getName());}}return importFieldName;}
执行如下main方法
public static void main(String[] args) {User user = new User();user.setAge(25);user.setFriendName(Arrays.asList("chq","tom","Thompson"));user.setName("ChenHQ");User user1 = new User();user1.setAge(28);user1.setFriendName(Arrays.asList("chq2","tom"));user1.setName("ChenHQ");//调用静态方法,获取需要比较的字段名集合List<String> importFieldName = getImportFieldName(user);//调用带参构造方法FieldBaseEquator fieldBaseEquator = new FieldBaseEquator(importFieldName,null);List<FieldInfo> diffFields = fieldBaseEquator.getDiffFields(user, user1);for (FieldInfo diffField : diffFields) {System.out.println(diffField);}}
此时运行结果如下:程序只检测 age,name字段,其他不做比较
这时,我们的底层对比已经差不多实现。只是对比过后返回的信息我们处理下,我们期望返回如下实体类集合形式,方便我们操作,来吧,我们进一步封装一下代码
public class ModifiedField {/*** 被修改的字段名*/private String fieldName;/*** 被修改的旧值*/private Object oldValue;/*** 被修改的新值*/private Object newValue;/*** 被修改的字段名中文解释*/private String remark;......}
/*** 比较并返回被修改过的对象属性 ModifiedField** @param modifyObject: 新值对象* @param oldObject: 旧值对象* @return*/public static List<ModifiedField> compareObject(Object modifyObject, Object oldObject) {//创建结果对象List<ModifiedField> result = new ArrayList<>();//获取对比字段List<String> importFieldName = getImportFieldName(modifyObject);FieldBaseEquator fieldBaseEquator = new FieldBaseEquator(importFieldName, null);//对比,返回属性值不同字段List<FieldInfo> diffFields = fieldBaseEquator.getDiffFields(modifyObject, oldObject);//封装成我们需要的对象for (FieldInfo diffField : diffFields) {ModifiedField modifiedField = new ModifiedField();modifiedField.setFieldName(diffField.getFieldName());modifiedField.setNewValue(diffField.getFirstVal());modifiedField.setOldValue(diffField.getSecondVal());//获取字段注解中文释义String remark = getRemarkByFieldName(modifyObject, diffField.getFieldName());modifiedField.setRemark(remark);result.add(modifiedField);}return result;}/*** 根据传入的对象,和字段名,获取对应注解的中文名称** @param obj* @param fieldName* @return*/private static String getRemarkByFieldName(Object obj, String fieldName) {Class<?> aClass = obj.getClass();try {Field field = aClass.getDeclaredField(fieldName);if (field.isAnnotationPresent(ImportantField.class)) {ImportantField annotation = field.getAnnotation(AnnotationDemo.class);return annotation.value();}} catch (Exception e) {e.printStackTrace();}return null;}
执行main方法
public static void main(String[] args) {User user = new User();user.setAge(25);user.setFriendName(Arrays.asList("chq","tom","Thompson"));user.setName("ChenHQ");User user1 = new User();user1.setAge(28);user1.setFriendName(Arrays.asList("chq2","tom"));user1.setName("ChenHQ");List<ModifiedField> modifiedFields = compareObject(user, user1);for (ModifiedField modifiedField : modifiedFields) {System.out.println(modifiedField);}}
如期而遇~,接下来的文案入库操作,我就不多说了。。愿你们码农之路,一路顺畅