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


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

  • BeanUtils的使用
    • 注解解决@DynamicUpdate
    • 自己写一个反射
    • 修改源码
【jpa中为null不更新实现的几种方式】
  • ps : 以下几种是StackOverflow等收集过来的方法,但是测试还是有问题(没有全部测试过,有空处理)
BeanUtils的使用
  • 目前BeanUtils还没有支持为空则不进行拷贝,但是有一个方法copyProperties(Object source, Object target, String… ignoreProperties)可以忽略部分值不进行拷贝,我们将需要忽略的值放入String数组中即可。(但在使用时还是存在问题,debug后还没解决,目前没有时间解决,ok的朋友可以告诉我)
  • 使用方法如下
public static String[] getNullPropertyNames (Object source) { final BeanWrapper src = https://www.it610.com/article/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 = https://www.it610.com/article/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

    推荐阅读