首页 > 编程语言 >Java实现记录对象修改前后的变化

Java实现记录对象修改前后的变化

时间:2023-03-21 14:14:22浏览次数:49  
标签:field ForUpdate Java 记录 builder 修改 Bean public append

需求描述
今天接到一个需求,修改数据时需要记录修改详情。详情包括,被修改的字段,修改前的值和修改后的值。

解决思路
分别比较修改前后两个Bean实例的所有成员变量,当值不一致时,记录变量名称,以及修改前后的值。 对于该方案,可以解决特定类型的Bean。 如果有其它类型的Bean也有这种需求,则需要新写一套逻辑,处理相应的需求。
上述方案不能复用,如果有多个这样的Bean需要比较,则每个Bean都需要新写一套逻辑。然而,利用泛型和反射技术,则可以达到一次编码,多处复用的效果
实现步骤
下面,就采用泛型和反射技术来实现上述需求

  • 自定义注解
    @Target(ElementType.FIELD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface ForUpdate {
        String fieldName() default "";
    }

 

  • 给Bean属性添加注解
    @Data
    @Builder
    public class Bean {
   
        private Long id; //不需要记录变化的字段,无需添加注解 @ForUpdate
       
        @ForUpdate(fieldName = "姓名") //需要记录变化的字段,需添加注解@ForUpdate
        private String name;

        @ForUpdate(fieldName = "年龄")
        private Integer age;
    }

 

  • 实现记录Bean修改明细
public class BeanUtils {
	
 	/**
     * 获取变更内容
     * @param newBean 更改前的Bean
     * @param oldBean 更改后的Bean
     * @param <T>
     * @return
     */
    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 = field.get(newBean);
                    Object oldValue = field.get(oldBean);
                    if(!Objects.equals(newValue, oldValue)) {
                        builder.append(field.getAnnotation(ForUpdate.class).fieldName()); //获取字段名称
                        builder.append(": 【更改前:");
                        builder.append(newValue);
                        builder.append(", 更改后:");
                        builder.append(oldValue);
                        builder.append("】\n");
                    }
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        }
        return builder.toString();
    }
}

 

  • 测试
	/**
 	* @Author tianyuxu
 	* @Since 2021/3/10 16:47
 	*/
 	public class BeanUtilsTest {
 		public static void main(String[] args) {
        	Bean bean1 = Bean.builder()
                .id(1L)
                .name("name1")
                .age(10)
                .build();

       	 Bean bean2 = Bean.builder()
                .id(1L)
                .name("name2")
                .age(20)
                .build();

      	  System.out.println(BeanUtils.getChangedFields(bean1, bean2));
      	  //最终输出 :
      	  // 姓名: 【更改前:name1, 更改后:name2】
		  // 年龄: 【更改前:10, 更改后:20】
   	 	}	
 	}

 

标签:field,ForUpdate,Java,记录,builder,修改,Bean,public,append
From: https://www.cnblogs.com/cuijinlong/p/17239805.html

相关文章

  • 在线直播系统源码,顶部标题栏的隐藏和显示、标题修改
    在线直播系统源码,顶部标题栏的隐藏和显示、标题修改1、顶部标题栏的隐藏:在我们的project工程下,找到“values”文件夹下的“themes.xml”或“styles.xml”文件(文件位置一......
  • Java基本类型和包装类什么情况下判断相等(“==“或“equals“)?
    Java中判断两个变量是否相等有两种方式:一种是利用==运算符,另一种是利用equals方法。如果变量是基本类型,那么使用==和使用equals会得到相同的结果,都是判断变量的值是否......
  • 使用Python标准库修改 Windows 系统代理
    转载:https://www.jianshu.com/p/6862d35e2855?tdsourcetag=s_pcqq_aiomsg Why在用Python编写一些网络相关的脚本时经常会需要连上特定代理。而面向Google编程又......
  • javaSE-day03(常用API一)
    API(ApplicationProgramminginterface)意思是应用程序编程接口,说人话就是Java帮我们写好的一些程序,如:类、方法等,我们直接拿过来用就可以解决一些问题。可以在API文档进行查......
  • JavaScript Scope All In One
    JavaScriptScopeAllInOneGlobalScope/全局作用域ScriptScope/脚本作用域LocalScope/局部作用域(函数作用域)BlockScope/块级作用域({}作用域)C......
  • Java入门_一维数组_第一题_升序数组
    声明咱是个新手,没啥技术只会最基础的,见谅哈。更简化的方法还请大佬指教。题目:已知有个升序数组的数组,要插入一个元素,该数组顺序依然是升序。例如:{25,49,74,......
  • java.io.IOException: Packet len1213486160 is out of range!
    部署otter,启动node的时候一直报错:2023-03-2110:39:24.615[main-SendThread(10.224.250.251:8080)]WARNorg.apache.zookeeper.ClientCnxn-Session0x0forserver......
  • java发送验证码
    导入maven包(commons-email)<dependency><groupId>org.apache.commons</groupId><artifactId>commons-email</artifactId><version>1.5</version></......
  • Java 获取最近12个月数据,包含当月数据
    List<String>dateList=newArrayList<>();Calendarcalendar=Calendar.getInstance();//月份最大为11最小为0所以设置初始月份时加1,需要获取到当前月份所以设置......
  • javaSE-day12(多线程)
    1.多线程的常用方法Thread提供了很多与线程操作相关的方法方法:publicvoidrun():线程的任务方法publicvoidstart():启动线程publicStringgetName():获取当前......