Java实现记录对象修改前后的变化
需求描述
今天接到一个需求,修改数据时需要记录修改详情。详情包括,被修改的字段,修改前的值和修改后的值。
解决思路
分别比较修改前后两个Bean实例的所有成员变量,当值不一致时,记录变量名称,以及修改前后的值。 对于该方案,可以解决特定类型的Bean。 如果有其它类型的Bean也有这种需求,则需要新写一套逻辑,处理相应的需求。
上述方案不能复用,如果有多个这样的Bean需要比较,则每个Bean都需要新写一套逻辑。然而,利用泛型和反射技术,则可以达到一次编码,多处复用的效果
实现步骤
下面,就采用泛型和反射技术来实现上述需求
- 自定义注解
1 2 3 4 5 6 | @Target (ElementType.FIELD) @Retention (RetentionPolicy.RUNTIME) @Documented public @interface ForUpdate { String fieldName() default "" ; } |
- 给Bean属性添加注解
1 2 3 4 5 6 7 8 9 10 11 12 | @Data @Builder public class Bean { private Long id; //不需要记录变化的字段,无需添加注解 @ForUpdate @ForUpdate (fieldName = "姓名" ) //需要记录变化的字段,需添加注解@ForUpdate private String name; @ForUpdate (fieldName = "年龄" ) private Integer age; } |
- 实现记录Bean修改明细
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | 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(); } } |
- 测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | /** * @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】 } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
2017-03-21 Jquery EaseyUi 提交请求
2017-03-21 easyui 保存后提示信息