首页 > 开发 > Java > 正文

详解SpringBoot实现JPA的save方法不更新null属性

2019-10-21 18:42:06
字体:
来源:转载
供稿:网友

序言:直接调用原生Save方法会导致null属性覆盖到数据库,使用起来十分不方便。本文提供便捷方法解决此问题。

核心思路

如果现在保存某User对象,首先根据主键查询这个User的最新对象,然后将此User对象的非空属性覆盖到最新对象。

核心代码

直接修改通用JpaRepository的实现类,然后在启动类标记此实现类即可。

一、通用CRUD实现类

public class SimpleJpaRepositoryImpl<T, ID> extends SimpleJpaRepository<T, ID> {  private final JpaEntityInformation<T, ?> entityInformation;  private final EntityManager em;  @Autowired  public SimpleJpaRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {    super(entityInformation, entityManager);    this.entityInformation = entityInformation;    this.em = entityManager;  }  /**   * 通用save方法 :新增/选择性更新   */  @Override  @Transactional  public <S extends T> S save(S entity) {    //获取ID    ID entityId = (ID) entityInformation.getId(entity);    Optional<T> optionalT;    if (StringUtils.isEmpty(entityId)) {      String uuid = UUID.randomUUID().toString();      //防止UUID重复      if (findById((ID) uuid).isPresent()) {        uuid = UUID.randomUUID().toString();      }      //若ID为空 则设置为UUID      new BeanWrapperImpl(entity).setPropertyValue(entityInformation.getIdAttribute().getName(), uuid);      //标记为新增数据      optionalT = Optional.empty();    } else {      //若ID非空 则查询最新数据      optionalT = findById(entityId);    }    //获取空属性并处理成null    String[] nullProperties = getNullProperties(entity);    //若根据ID查询结果为空    if (!optionalT.isPresent()) {      em.persist(entity);//新增      return entity;    } else {      //1.获取最新对象      T target = optionalT.get();      //2.将非空属性覆盖到最新对象      BeanUtils.copyProperties(entity, target, nullProperties);      //3.更新非空属性      em.merge(target);      return entity;    }  }  /**   * 获取对象的空属性   */  private static String[] getNullProperties(Object src) {    //1.获取Bean    BeanWrapper srcBean = new BeanWrapperImpl(src);    //2.获取Bean的属性描述    PropertyDescriptor[] pds = srcBean.getPropertyDescriptors();    //3.获取Bean的空属性    Set<String> properties = new HashSet<>();    for (PropertyDescriptor propertyDescriptor : pds) {      String propertyName = propertyDescriptor.getName();      Object propertyValue = srcBean.getPropertyValue(propertyName);      if (StringUtils.isEmpty(propertyValue)) {        srcBean.setPropertyValue(propertyName, null);        properties.add(propertyName);      }    }    return properties.toArray(new String[0]);  }}

二、启动类

@EnableJpaRepositories(value = "com.hehe.repository", repositoryBaseClass = SimpleJpaRepositoryImpl.class)@SpringBootApplicationpublic class JpaApplication {  public static void main(String[] args) {    SpringApplication.run(JpaApplication.class, args);  }}

三、实体类和通用Save

@Entity@Table(name = "T_USER")@JsonIgnoreProperties({"handler","hibernateLazyInitializer"})public class User {  @Id  private String userId;  private String username;  private String password;  //省略GET/SET}public interface UserRepository extends JpaRepository<User, String> {}

四、配置文件 application.yml

spring: datasource:  url: jdbc:mysql://localhost:3306/socks?useSSL=false  username: root  password: root  driver-class-name: com.mysql.jdbc.Driver

五、数据库脚本

drop table if exists t_user;create table t_user ( user_id varchar(50), username varchar(50), password varchar(50));insert into t_user values ('1', 'admin', 'admin');insert into t_user values ('2', 'yizhiwazi', '123456');

六、测试代码

@RestControllerpublic class UserController {  @Autowired  private UserRepository userRepository;  @RequestMapping("/")  public User get() {    userRepository.save(new User("1", "", null));    return userRepository.findById("1").get();  }}

整体结构图

在实际项目中,可以直接复制SimpleJpaRepositoryImpl使用,并不影响原有的其它API。

SpringBoot,JPA,save,null

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持CuoXin错新网。


注:相关教程知识阅读请移步到JAVA教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表