目录
问题描述
解决思路
解决方法
Spring Data JPA是我们经常使用的一个数据库持久化的框架,当我们使用JPA进行更新操作的时候会遇到一个坑,今天我就将之前JPA遇到的这个坑进行更加深入的剖析,帮助大家避免这类问题多发生,当然这只是给出了部分解决方法,相信大佬们会有更优雅的解决方法,也把这些优雅的方法放到评论区,我会第一时间把这些好的方法补充进去,供大家参考。这里小编就把自己的解决方法提供给大家。如有问题,还肯大家批评指正。
问题描述
由于jpa中没有现成的update方法,所以经常使用save方法来实现简单的更新操作,jpa会根据id的值自动识别,进行save和update的操作。当进行更改数据库的部分字段的时候,部分未修改的字段如果不传值的话,就会遇到问题,这些未修改的值就会按null进行赋值。这里就遇到了开头说的jpa更新操作的坑。
下面举个🌰
User表有user_name,id,phone,email,password字段,只修改user_name和phone,
修改操作:
1.拿到前端传递的实体user;
2.根据user的userId,拿到原始的对象(修改前的user对象);
Long userId = user.getUserId(); //获取userId
User oldUser = userDao.findByUserId(userId); //根据userId得到修改前原user对象
3.将前端传递过来的不为空的参数,也就是要修改的值copy复制来覆盖原始对象
由于一般字段个数很多,我们进场使用spring提供的BeanUtils工具类来进行实体的拷贝操作,
BeanUtils.copyProperties(sourcr,target);
在这个拷贝操作的时候,未赋值的对象实体是null,就会覆盖掉从数据中查询的实体对象的属性,导致这次save方法让原本有值的对象被null覆盖。
我们通过分析是由于copy的时候,把null值也赋值给了PO对象,所以我们通过分析产生问题的原因 来实现问题的解决。
解决思路
1.对每一个参数都进行判断,不为空再更新
2.编写一个工具类,通过工具实现属性的copy
解决方法
1.最简单的方法
就是对传入的参数一个一个的进行判断,如果传的参数不是null,说明这个参数就是我们想进行更新的字段,这样我们就避免使用BeanUtils的copyProperties,但是这种方法非常不优雅,字段少的时候使用还是可以的,但是如果对象中的字段非常的多,每一个字段都需要进行是否为空的校验的话,是非常烦人的,非常不优雅,下面我们优雅的实现一个工具类,实现这个功能。
2.编写一个工具类实现非空值的拷贝
/**
* 更新工具类(忽略为null的字段)
*/
public class UpdateUtil {
/**
* 所有为空值的属性都不copy
* @param source
* @param target
*/
public static void copyNullProperties(Object source, Object target) {
BeanUtils.copyProperties(source, target, getNullField(source));
}
/**
* 获取属性中为空的字段
*
* @param target
* @return
*/
private static String[] getNullField(Object target) {
BeanWrapper beanWrapper = new BeanWrapperImpl(target);
PropertyDescriptor[] propertyDescriptors = beanWrapper.getPropertyDescriptors();
Set<String> notNullFieldSet = new HashSet<>();
if (propertyDescriptors.length > 0) {
for (PropertyDescriptor p : propertyDescriptors) {
String name = p.getName();
Object value = beanWrapper.getPropertyValue(name);
if (Objects.isNull(value)) {
notNullFieldSet.add(name);
}
}
}
String[] notNullField = new String[notNullFieldSet.size()];
return notNullFieldSet.toArray(notNullField);
}
}
在进行调用的时候,就用这个工具类实现属性的拷贝。这样就优雅的实现了上面的功能。