目录

问题描述

解决思路

解决方法


Spring Data JPA是我们经常使用的一个数据库持久化的框架,当我们使用JPA进行更新操作的时候会遇到一个坑,今天我就将之前JPA遇到的这个坑进行更加深入的剖析,帮助大家避免这类问题多发生,当然这只是给出了部分解决方法,相信大佬们会有更优雅的解决方法,也把这些优雅的方法放到评论区,我会第一时间把这些好的方法补充进去,供大家参考。这里小编就把自己的解决方法提供给大家。如有问题,还肯大家批评指正。

java jpa 不创建表 jpa为null不更新_字段

 

问题描述

由于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对象,所以我们通过分析产生问题的原因 来实现问题的解决。

java jpa 不创建表 jpa为null不更新_java_02

 

解决思路

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);
  }
}

在进行调用的时候,就用这个工具类实现属性的拷贝。这样就优雅的实现了上面的功能。

java jpa 不创建表 jpa为null不更新_工具类_03