序言:直接调用原生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。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://www.jianshu.com/p/4931fbc52ea1