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

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

核心思路

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

核心代码

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

一、通用CRUD实现类

public class SimpleJpaRepositoryImpl extends SimpleJpaRepository {

private final JpaEntityInformation entityInformation;

private final EntityManager em;

@Autowired

public SimpleJpaRepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager) {

super(entityInformation, entityManager);

this.entityInformation = entityInformation;

this.em = entityManager;

}

/**

* 通用save方法 :新增/选择性更新

*/

@Override

@Transactional

public S save(S entity) {

//获取ID

ID entityId = (ID) entityInformation.getId(entity);

Optional 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 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)

@SpringBootApplication

public 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 {

}

四、配置文件 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');

六、测试代码

@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。

23b9235e07d99fa2ea6e6794083b6397.png

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

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值