关键字: JPA更新为null,JPA save null,JPA保存为null

今天使用jpa的save方法时发现null字段也会被更新到数据库,这个直接把数据库数据覆盖的行为很可怕,果断研究了一下怎样能不保存null值。

解决方法:

  1. 实体类加@DynamicInsert(true)/@DynamicUpdate(true)注解;
  2. 扩展SimpleJpaRepository覆盖save方法;
  3. 启动类添加@EnableJpaRepositories(repositoryBaseClass = ZeusJpaRepository.class)注解;

一.扩展SimpleJpaRepository覆盖save方法

ZeusJpaRepository.java

package com.lmt.zeus.jpa;import com.lmt.zeus.parent.utils.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;import javax.persistence.EntityManager;
import java.util.Optional;/*** @description 扩展SimpleJpaRepository,save()时不更新null字段** @author 隐* @date 2020/3/4 18:01* @since JDK1.8*/
@Slf4j
public class ZeusJpaRepository<T, ID> extends SimpleJpaRepository<T, ID> {private JpaEntityInformation<T, ?> jpaEntityInformation;/*** Creates a new {@link ZeusJpaRepository} to manage objects of the given {@link JpaEntityInformation}.** @param entityInformation must not be {@literal null}.* @param entityManager     must not be {@literal null}.*/@Autowiredpublic ZeusJpaRepository(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {super(entityInformation, entityManager);this.jpaEntityInformation = entityInformation;}/*** 覆盖原来实现,不更新null字段* @author 隐* @date 2020-03-16* @param entity* @param <S>* @return*/@Overridepublic <S extends T> S save(S entity) {ID id = (ID) jpaEntityInformation.getId(entity);if (id != null) {Optional<T> op = findById(id);if (op.isPresent()) {T t = op.get();BeanUtils.copyPropertiesWithoutNull(entity, t);entity = (S) t;}}return super.save(entity);}
}

BeanUtils.java

package com.lmt.zeus.parent.utils;import org.springframework.beans.FatalBeanException;import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;/*** @description Bean拷备、map转换工具类* @author 隐* @date 2018/11/8 17:55* @since JDK1.8*/
public class BeanUtils extends org.springframework.beans.BeanUtils {/*** bean copy不复制null值* @author 隐* @date 2018-11-10* @param source* @param target*/public static void copyPropertiesWithoutNull(Object source, Object target) {if(source == null || target == null){return;}Class<?> actualEditable = target.getClass();Class<?> sourceClass = source.getClass();PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);for (PropertyDescriptor targetPd : targetPds) {if(targetPd.getWriteMethod() == null) {continue;}PropertyDescriptor sourcePd = getPropertyDescriptor(sourceClass, targetPd.getName());if(sourcePd == null || sourcePd.getReadMethod() == null) {continue;}try {Method readMethod = sourcePd.getReadMethod();if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {readMethod.setAccessible(true);}Object value = readMethod.invoke(source);setValue(target, targetPd, value);} catch (Exception ex) {throw new FatalBeanException("Could not copy properties from source to target", ex);}}}/*** 设置值到目标bean* @param target* @param targetPd* @param value* @throws IllegalAccessException* @throws InvocationTargetException*/private static void setValue(Object target, PropertyDescriptor targetPd, Object value) throws IllegalAccessException, InvocationTargetException {// 这里判断以下value是否为空if (value != null) {Method writeMethod = targetPd.getWriteMethod();if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {writeMethod.setAccessible(true);}writeMethod.invoke(target, value);}}}

二、启动类

import com.lmt.zeus.jpa.ZeusJpaRepository;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;/*** @description Spring Boot启动类** @author 隐* @date 2020/3/16 10:10* @since JDK1.8*/
@SpringBootApplication
@EnableTransactionManagement
@ServletComponentScan
@EnableScheduling
@EnableJpaRepositories(repositoryBaseClass = ZeusJpaRepository.class)
public class CoinTradeApp {public static void main(String [] args) {SpringApplication.run(CoinTradeApp.class, args);}}

注:实体类上不要忘了加@DynamicInsert(true)/@DynamicUpdate(true)注解;

ps:这里还有个坑如果根据id查出来直接在查出的实体上设置某字段为null,再保存时仍可以把null字段保存到数据库(因为session缓存原因),所以save方法执行时最好不要直接拿查出的实体修改,还是new一个比较安全。


                    欢迎关注「Java牧码人」

                   追求技术的路上永无止境

JPA踩坑记:Spring Data Jpa 更新为null的问题(save方法保存时null值会被更新到数据库)相关推荐

  1. JPA、Hibernate和Spring Data JPA区别

    大家好,我是神韵,是一个技术&生活博主.出文章目的主要是两个,一是好记忆不如烂笔头,记录总结中提高自己.二是希望我的文章可以帮到大家.欢迎来点赞打卡,你们的行动将是我无限的动力. 本篇主题是: ...

  2. mysql jpa缓存,如何在Spring Data JPA CRUDRepository中添加缓存功能

    I want to add "Cacheable" annotation in findOne method, and evict the cache when delete or ...

  3. Spring Data JPA用法详解

    Spring Data JPA: JPA(Java Persistence API)即java持久化API,它的出现主要是为了简化持久层开发以及整合ORM技术,结束Hibernate.TopLink. ...

  4. springdatajpa命名规则_简单了解下spring data jpa

    公司准备搭建一个通用框架,以后项目就用统一一套框架了 以前只是听过jpa,但是没有实际用过 今天就来学习下一些简单的知识 什么是JPA 全称Java Persistence API,可以通过注解或者X ...

  5. SpringBoot学习笔记:Spring Data Jpa的使用

    更多请关注公众号 Spring Data Jpa 简介 JPA JPA(Java Persistence API)意即Java持久化API,是Sun官方在JDK5.0后提出的Java持久化规范(JSR ...

  6. hql实例 jpa_SpringBoot学习笔记九:Spring Data Jpa的使用

    Spring Data Jpa 简介 JPA JPA(Java Persistence API)意即Java持久化API,是Sun官方在JDK5.0后提出的Java持久化规范(JSR 338,这些接口 ...

  7. 简述 JPA 与 Spring Data JPA 与 Hibernate

    1.JPA是什么?以及相关概述 JPA的是 Java Persistence API 的简写,是Sun官方提出的一种ORM规范! Sun提出此规范有2个原因: 1.简化现有Java EE和Java S ...

  8. SpringBoot22-spingboot数据访问-Spring Data JPA

    一:点睛Spring Data JPA 1,什么事Spring Data JPA 我们知道Hibernate是数据访问解决技术的绝对霸主,使用O/R映射技术实现数据访问,o/r映射即将领域模型类和数据 ...

  9. Springboot整合Spring Data JPA

    1 Spring Data JPA 1.Spring Data JPA的概念 在介绍Spring Data JPA的时候,我们首先认识下Hibernate.Hibernate是数据访问解决技术的绝对霸 ...

最新文章

  1. 格式化_icecream_python
  2. python 深度 视差 计算_开源双目视觉BM算法-Matlab/Python/Javascript
  3. VBOX Ubuntu设置与Windows的共享文件夹
  4. 什么是java本地方法?什么,还没听说过java的native关键字?真的该学学了!
  5. JVM的常用配置参数
  6. [转]JS中判断鼠标按键判断
  7. 串行线路上传输数据报的非标准协议:SLIP
  8. PHP中empty,is_null,isset中的异同和功能
  9. BGP——权重选路(讲解+配置命令)
  10. elasticsearch设置为windows系统服务
  11. 主题:web.config中AppSettings和ConnectionStrings的区别
  12. html object 播放swf,JS进阶篇--swfobject.js视频播放插件
  13. 深度可分离卷积解析 - MobileNetV1
  14. linux 查看tps命令,Linux系统一些系统查看指令
  15. C语言典型例题四——斐波那契数列
  16. Word如何转PDF
  17. MFC 在Edit Control输入完成后按下回车键希望直接执行某个函数
  18. c语言程序设计指针何钦铭ppt,C语言程序设计 教学课件 作者 何钦铭 c2.ppt
  19. 腾讯社招iOS面试记录
  20. 区块链世界的流量聚集地

热门文章

  1. Java学习需要具备什么条件?
  2. xilinx器件系统时钟接在GTX时钟问题解决
  3. Python报错:NameError: name 'reduce' is not defined 和 reduce()函数介绍
  4. 【web前端特效源码】使用 HTMLCSSJavaScript实现各种跳跃浮动慢跑翻转旋转坠落的魔幻文字动画效果~太上头了~/动画效果|前端开发|IT软件开发基础入门教程|网页制作|网站开发定制
  5. ZooKeeper之zoo.cfg配置
  6. 扫雷游戏 P2670 [NOIP2015 普及组]
  7. 计算机网络管理员工作周记,计算机java开发实习周记20篇
  8. Python高效办公|批量经纬度转地址
  9. [小工具] chrome上日语翻译工具
  10. VMware version虚拟机镜像的浏览器连不上网的问题