jpa中为null不更新实现的几种方式

jpa中为null不更新实现的几种方式

  • BeanUtils的使用
    • 注解解决@DynamicUpdate
    • 自己写一个反射
    • 修改源码

  • ps : 以下几种是StackOverflow等收集过来的方法,但是测试还是有问题(没有全部测试过,有空处理)

BeanUtils的使用

  • 目前BeanUtils还没有支持为空则不进行拷贝,但是有一个方法copyProperties(Object source, Object target, String… ignoreProperties)可以忽略部分值不进行拷贝,我们将需要忽略的值放入String数组中即可。(但在使用时还是存在问题,debug后还没解决,目前没有时间解决,ok的朋友可以告诉我)
  • 使用方法如下
public static String[] getNullPropertyNames (Object source) {
    final BeanWrapper src = new BeanWrapperImpl(source);
    java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();

    Set emptyNames = new HashSet();
    for(java.beans.PropertyDescriptor pd : pds) {
        Object srcValue = src.getPropertyValue(pd.getName());
        if (srcValue == null) emptyNames.add(pd.getName());
    }
    String[] result = new String[emptyNames.size()];
    return emptyNames.toArray(result);
}

// then use Spring BeanUtils to copy and ignore null
public static void myCopyProperties(Object src, Object target) {
    BeanUtils.copyProperties(src, target, getNullPropertyNames(src))
}

其中java8可以采取一些方式

public static String[] getNullPropertyNames(Object source) {
    final BeanWrapper wrappedSource = new BeanWrapperImpl(source);
    return Stream.of(wrappedSource.getPropertyDescriptors())
            .map(FeatureDescriptor::getName)
            .filter(propertyName -> wrappedSource.getPropertyValue(propertyName) == null)
            .toArray(String[]::new);
}

我们查看BeanUtils的源码可以发现,理论上应该时可以的

 public static void copyProperties(Object source, Object target, String... ignoreProperties) throws BeansException {
        copyProperties(source, target, (Class)null, ignoreProperties);
    }

    private static void copyProperties(Object source, Object target, @Nullable Class editable, @Nullable String... ignoreProperties) throws BeansException {
        Assert.notNull(source, "Source must not be null");
        Assert.notNull(target, "Target must not be null");
        Class actualEditable = target.getClass();
        if (editable != null) {
            if (!editable.isInstance(target)) {
                throw new IllegalArgumentException("Target class [" + target.getClass().getName() + "] not assignable to Editable class [" + editable.getName() + "]");
            }

            actualEditable = editable;
        }

        PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
        List ignoreList = ignoreProperties != null ? Arrays.asList(ignoreProperties) : null;
        PropertyDescriptor[] var7 = targetPds;
        int var8 = targetPds.length;

        for(int var9 = 0; var9 < var8; ++var9) {
            PropertyDescriptor targetPd = var7[var9];
            Method writeMethod = targetPd.getWriteMethod();
            if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {
                PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
                if (sourcePd != null) {
                    Method readMethod = sourcePd.getReadMethod();
                    if (readMethod != null && ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
                        try {
                            if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
                                readMethod.setAccessible(true);
                            }

                            Object value = readMethod.invoke(source);
                            if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
                                writeMethod.setAccessible(true);
                            }

                            writeMethod.invoke(target, value);
                        } catch (Throwable var15) {
                            throw new FatalBeanException("Could not copy property '" + targetPd.getName() + "' from source to target", var15);
                        }
                    }
                }
            }
        }

    }


当条件 writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName())) 成立的时候则不进行拷贝,其中ignoreList是我们传入的数据。

注解解决@DynamicUpdate

  • @DynamicUpdate 与 @DynamicInsert 都是参数为空的不进行更新或者插入,需要将默认值value置为true(默认为true,但是不同版本可能不一样,可点进源码查看一下)

自己写一个反射

  • 则里就不给出方式了,思路大概是先查出需要修改的对象和需要修改的对象进行比较。通过反射,将新的对象中全部的参数获取出来(也可以通过get set方法,但是没必要)进行判断,如果为null,则进行赋值。

修改源码

  • 个人感觉没必要,也是基于上面第一第三两种方式进行修改,需要的可以参考这篇博客 https://www.jianshu.com/p/4931fbc52ea1

你可能感兴趣的:(jpa)