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);}}

如期而遇~,接下来的文案入库操作,我就不多说了。。愿你们码农之路,一路顺畅

(0)

相关推荐

  • 吊打面试官系列:说说hashCode和equals方法

    首先我们需要知道hashCode方法和equals方法都是属于Object类的方法.既然属于Object中public修饰的方法,那言外之就是所有对象默认都有这两个方法,只是有时候有的对象已对这两个方 ...

  • TkMybatis常用方法

    TkMybatis常用方法

  • VBA基础一:对象、属性、方法、变量

    '1.工作簿(Workbooks) ' Workbooks(N)第N个工作簿 ' Workbooks ('工作簿名') ' ActiveWorkbook 活动工作簿 ' ThisWorkBook '代 ...

  • Java 获取PDF中的数字签名信息

    一.概述及程序环境要求 本文以Java代码演示如何获取PDF文档中的数字签名信息,包括签名人.签名位置.日期.原因.联系方式.签名在文档中的坐标等等. 程序环境包括: Spire.Pdf.jar(ja ...

  • java获取当月的第一天或最后一天

    方式共有两种,使用java.util.Calendar日历类实现 第一种: SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd&q ...

  • 男性在短时间内获取两次精液,质量会下降吗?

    当女性临近排卵日时,属于易孕阶段,不少夫妻都会选择在这一个时期提高同房的频率,以提高受孕率. 但也有很多夫妻认为,如果男性禁欲时间太短,那么精子质量也会下降,影响到胚胎的质量. 禁欲可以提高精子质量? ...

  • Java中的匿名对象

    一:匿名对象 正常情况下一个对象有堆内存空间和指向堆内存的栈内存空间,如果一个对象只有堆内存空间却没有栈内存指向,这样的对象就叫做匿名对象. DEMO:观察匿名对象 其实匿名对象还可以作为方法的实际参 ...

  • 梦幻西游:土豪鉴定灵饰引起公愤,炸出两件120三属性,价值10万

    鉴定灵饰装备与鉴定普通人物装备不同的地方就是成就,鉴定灵饰只有两种成就,即超级简易以及三属性相同成就.这两种成就无论鉴定出了哪一种,就意味着玩家逆袭的几率很高,可以说与无级别成就相当.比如有幸鉴定出了 ...

  • TBC猎人P1阶段毕业近战武器竟是两个蓝装,属性胜过凤凰双刃!

    怀旧服冷知识,拳套算钝器.测试服实测证实,给钝器用的精金磨刀石增伤和暴击对远程攻击有效. 双手武器中只有法杖算钝器,其他能拿的都是利器. 双持钝器=2把武器基础属性加成+平衡石(12伤害 稳固无效,1 ...

  • 给小白讲java中两大怪物,附带面试题!

    最近老是有小伙伴问类和Object相关的问题,感觉还是很多人对此不是很明白,那我们今天就干掉这两个怪物. 如何搞定20k的面试小抄 类介绍 Java 程序是由若干个类组成的,类也是面向对象编程思想的具 ...

  • 诚之和:教你使用Java实现树形菜单对象 实例代码解析

    本文实例为大家分享了java实现树形菜单对象的具体代码,供大家参考,具体内容如下 1.SysMenu package com.zy.shiro.domain;import com.baomidou.m ...