比较实体类前后差异返回差异字段和内容,用于记录日志使用

大图

1. 代码

话不多说直接上代码

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;


/**
 * 比较实体类前后差异返回差异字段和内容
 *
 * @author lhn
 * @createDate 2020/09/03 10:51
 */
public class BeanCompareUtils<T> {
    public String contrastObj(Object oldBean, Object newBean) {
        String str="";
        //if (oldBean instanceof SysConfServer && newBean instanceof SysConfServer) {
        T pojo1 = (T) oldBean;
        T pojo2 = (T) newBean;
        try {
            Class clazz = pojo1.getClass();
            Field[] fields = pojo1.getClass().getDeclaredFields();
            int i=1;
            for (Field field : fields) {
                if("serialVersionUID".equals(field.getName())){
                    continue;
                }
                PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz);
                Method getMethod = pd.getReadMethod();
                Object o1 = getMethod.invoke(pojo1);
                Object o2 = getMethod.invoke(pojo2);
                if(o1==null || o2 == null){
                    continue;
                }
                if (!o1.toString().equals(o2.toString())) {
                    if(i!=1){
                        str+=";";
                    }
                    str+=i+"、字段名称"+field.getName()+",旧值:"+o1+",新值:"+o2;
                    i++;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        // }
        return str;
    }

    public static void main(String[] args) {
        BeanCompareUtils beanCompareUtils = new BeanCompareUtils();
        MebUserDto mebUserDto = new MebUserDto();
        mebUserDto.setParkUserId("1");
        mebUserDto.setMobileNumber("18851815112");
        mebUserDto.setUserStatus(1);
        MebUserDto mebUserDto1 = new MebUserDto();
        mebUserDto1.setParkUserId("2");
        mebUserDto1.setMobileNumber("18851815112");
        mebUserDto1.setUserStatus(2);
        System.out.println(beanCompareUtils.contrastObj(mebUserDto,mebUserDto1));
    }
}

运行结果

运行结果

可以使用 Spring AOP 的方式,在数据更新时拦截相关方法,将数据修改前后的差异信息记录下来,然后将记录返回给前端。以下是简单的代码示例: 首先定义一个切面类,用于拦截数据更新方法: ```java @Aspect @Component public class DataChangeAspect { @Autowired private HttpServletRequest request; @Pointcut("execution(public * com.example.demo.service.*.update*(..))") public void updatePointcut() {} @Around("updatePointcut()") public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { // 获取方法名 String methodName = joinPoint.getSignature().getName(); // 获取参数列表 Object[] args = joinPoint.getArgs(); // 获取被更新的实体对象 Object entityObject = args[0]; // 获取原始实体对象 Object originalObject = getOriginalEntityObject(entityObject); // 执行方法 Object result = joinPoint.proceed(); // 记录数据差异返回给前端 recordDataChange(originalObject, entityObject); return result; } /** * 获取原始实体对象 */ private Object getOriginalEntityObject(Object entityObject) { // 根据实体对象的 ID 查询原始实体对象 // 这里需要根据具体业务进行实现 Long entityId = ((BaseEntity) entityObject).getId(); return entityManager.find(entityObject.getClass(), entityId); } /** * 记录数据差异返回给前端 */ private void recordDataChange(Object originalObject, Object entityObject) { // 计算数据差异 Map<String, Object> diffMap = getDiff(originalObject, entityObject); // 将差异信息记录日志中 String diffStr = convertDiffMapToString(diffMap); logService.info("数据修改前后差异:" + diffStr); // 将差异信息返回给前端 request.setAttribute("dataDiff", diffMap); } /** * 计算实体对象的属性差异信息 */ private Map<String, Object> getDiff(Object originalObject, Object entityObject) { Map<String, Object> diffMap = new HashMap<>(); Class<?> clazz = entityObject.getClass(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { // 非持久化字段不参与差异计算 if (!field.isAnnotationPresent(Column.class)) { continue; } String fieldName = field.getName(); Object originalValue = ReflectionUtils.getFieldValue(originalObject, fieldName); Object newValue = ReflectionUtils.getFieldValue(entityObject, fieldName); if (originalValue == null || !originalValue.equals(newValue)) { diffMap.put(fieldName, newValue); } } return diffMap; } /** * 将差异信息转换为字符串 */ private String convertDiffMapToString(Map<String, Object> diffMap) { StringBuilder sb = new StringBuilder(); for (Map.Entry<String, Object> entry : diffMap.entrySet()) { sb.append(entry.getKey()).append(": ").append(entry.getValue()).append(","); } if (sb.length() > 0) { sb.deleteCharAt(sb.length() - 1); } return sb.toString(); } } ``` 然后,使用 AOP 拦截 Spring Data JPA 的 save 或 update 方法: ```java @Aspect @Component public class JpaRepositoryAspect { @Autowired private HttpServletRequest request; @Around("execution(public * org.springframework.data.jpa.repository.JpaRepository+.save(..)) || execution(public * org.springframework.data.jpa.repository.JpaRepository+.saveAndFlush(..))") public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { // 获取被保存或更新的实体对象 Object entityObject = joinPoint.getArgs()[0]; // 记录数据变化并返回给前端 request.setAttribute("originalData", entityObject); Object result = joinPoint.proceed(); request.setAttribute("modifiedData", entityObject); return result; } } ``` 最后,在 Controller 中获取前面拦截器中记录的数据差异信息和修改前后的实体对象: ```java @RestController public class DataController { @GetMapping("/users/{userId}") public User getUser(@PathVariable Long userId, HttpServletRequest request) { // 查询用户 User user = userRepository.findById(userId).orElse(null); // 获取数据差异信息 Map<String, Object> dataDiff = (Map<String, Object>) request.getAttribute("dataDiff"); // 获取修改前的实体对象 User originalData = (User) request.getAttribute("originalData"); // 获取修改后的实体对象 User modifiedData = (User) request.getAttribute("modifiedData"); // 合并差异信息到修改后的实体对象中 mergeDiffIntoModifiedData(modifiedData, dataDiff); return modifiedData; } /** * 将数据差异合并到修改后的实体对象中 */ private void mergeDiffIntoModifiedData(User modifiedData, Map<String, Object> dataDiff) { if (dataDiff == null || dataDiff.isEmpty()) { return; } BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(modifiedData); beanWrapper.setAutoGrowNestedPaths(true); for (Map.Entry<String, Object> entry : dataDiff.entrySet()) { String fieldName = entry.getKey(); Object value = entry.getValue(); beanWrapper.setPropertyValue(fieldName, value); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值