jpa中为null不更新实现的几种方式
jpa中为null不更新实现的几种方式
- BeanUtils的使用
- 注解解决@DynamicUpdate
- 自己写一个反射
- 修改源码
- ps : 以下几种是StackOverflow等收集过来的方法,但是测试还是有问题(没有全部测试过,有空处理)
- 目前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
推荐阅读
- vue组件中为何data必须是一个函数()
- Java中有关Null的9件事
- The|The getter 'data' was called on null , Receiver: null, Tried calling
- Unable|Unable to add window -- token null is not valid; is your activity running?
- spring|spring data JPA native query with pagination
- JPA大坑 ,无法像mybaits一样在current_at字段,自动生成创建时间
- 面试突击19(为什么ConcurrentHashMap不允许插入null值())
- 为什么我不建议你用去 “ ! = null " 做判空()
- dart系列之:和null说再见,null使用最佳实践
- JPA|JPA 实体脏检查与存储同步(Dirty & Flush)