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

时间:2021-12-10 15:48:40

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

核心思路

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

核心代码

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

一、通用crud实现类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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]);
  }
}

二、启动类

?
1
2
3
4
5
6
7
8
@enablejparepositories(value = "com.hehe.repository", repositorybaseclass = simplejparepositoryimpl.class)
@springbootapplication
public class jpaapplication {
 
  public static void main(string[] args) {
    springapplication.run(jpaapplication.class, args);
  }
}

三、实体类和通用save

?
1
2
3
4
5
6
7
8
9
10
11
12
@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

?
1
2
3
4
5
6
spring:
 datasource:
  url: jdbc:mysql://localhost:3306/socks?usessl=false
  username: root
  password: root
  driver-class-name: com.mysql.jdbc.driver

五、数据库脚本

?
1
2
3
4
5
6
7
8
9
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');

六、测试代码

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@restcontroller
public 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属性

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://www.jianshu.com/p/4931fbc52ea1