Jpa 插入更新如何过滤null值

2023-05-16

使用Jpa时,默认的save方法会将entity中null的值也更新到数据库,这对与存在默认值或者更新接口将直接导致错误的记录产生,那么如何解决这个问题?

Hibernate提供了两个注解


@DynamicInsert: 
For inserting, should this entity use dynamic sql generation where only non-null columns get referenced in the prepared sql statement?  

@DynamicUpdate: 
For updating, should this entity use dynamic sql generation where only changed columns get referenced in the
prepared sql statement?

  

DynamicInsert 很好理解,只有非null的值会拼接成sql,而 DynamicUpdate 容易产生误解,官方解释是只有当值改变的时候才会拼接到sql中。如果原先该字段的值已经设置了值,此时更新如果不传递该字段,那么数据库中该字段值会更新为null,这很明显与我们的初衷不符合。

通过查看源码可知, DefaultFlushEntityEventListener 的 dirtyCheck的方法检查那些字段的值需要更新,涉及到到检查的过程分3个方面

1.首先通过 session.getInterceptor() 检查

2.其次 如果entity实现了 SelfDirtinessTracker接口,通过 $$_hibernate_getDirtyAttributes返回需要检查的属性(侵入性太强);

否则根据自定义的策略  session.getFactory().getCustomEntityDirtinessStrategy()检查。

3.通过EntityPersister的findDirty最终调用TypeHelper.findDirty静态方法,核心代码如下


final boolean dirty = currentState[i] != LazyPropertyInitializer.UNFETCHED_PROPERTY &&
      ( previousState[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY ||
            ( properties[i].isDirtyCheckable()
                  && properties[i].getType().isDirty( previousState[i], currentState[i], includeColumns[i], session ) ) );
  

最终通过Objects.deepEquals( one, another )的判断值是否一致。

所以我们可以通过自定义Interceptor或者CustomEntityDirtinessStrategy添加自己的检查逻辑,并在application.properties添加配置如下


spring.jpa.properties.hibernate.session_factory.interceptor=**.xxInterceptor (5.2以下使用 hibernate.ejb.interceptor)
spring.jpa.properties.hibernate.entity_dirtiness_strategy=**.CustomEntityDirtinessStrategy  

附上我的解决方案,参考TypeHelper.findDirty方法实现


public class JpaFilterNullInterceptor extends EmptyInterceptor {


    @Override
    public int[] findDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState, String[] propertyNames, Type[] types) {
        int[] results = null;
        int count = 0;
        int span = propertyNames.length;

        for ( int i = 0; i < span; i++ ) {
            // 如果字段是null,默认不插入或者更新
            final boolean dirty = null != currentState[i]
                    && !Objects.deepEquals(currentState[i], previousState[i]);
            if ( dirty ) {
                if ( results == null ) {
                    results = new int[span];
                }
                results[count++] = i;
            }
        }

        // 数据完全一致,返回空数组确保不会执行默认的逻辑
        if ( count == 0 ) {
            return new int[0];
        }
        else {
            return ArrayHelper.trim(results, count);
        }
    }
}  
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Jpa 插入更新如何过滤null值 的相关文章

  • 使用 jq 过滤空值和/或 null 值

    我有一个包含 jsonlines 的文件 想找到空值 name Color TV price 1200 available name DVD player price 200 color null 并希望输出空和 或空值及其键 availa
  • CrudRepository 未从 schema.sql 读取数据

    Setup 我有一个带有简单 Entity Customer 对象和 CustomerRepository 的 spring boot 应用程序 我想用描述的测试数据预加载数据库在我的另一个问题中 https stackoverflow c
  • 从 EntityManagerFactory 连接 EntityManager 的问题

    我知道 spring 有它自己的 JPA 对象工厂 但我想让它按原样工作 从那里我将研究最佳实践 我只是处于理解过程中 这是我尝试为其生成 bean 的实际代码 EntityManagerFactory emf Persistence cr
  • Spring Data JPA 和 Querydsl 使用 bean/构造函数投影获取列子集

    我有一个实体类如下 Entity public class UserDemo implements Serializable Id private Long id private String username private String
  • JPA:EntityManager 保存数据花费的时间太长

    我有一个 csv 数据文件 总共有 100 000 条记录 我正在迭代记录并尝试为每条记录更新 5 个表 这是示例数据 EAN Code Site Genric Material Material Sap Ean Code Style Co
  • HibernateTemplate 可以与 EntityManager 共存吗?

    我们有一个 spring 3 应用程序 它仍然使用已弃用的HibernateTemplate为了持久性并希望迁移到更现代的 JPAEntityManager 是否可以在迁移过程中并行使用这两个 API 甚至可能在单个事务中同时使用 以便我们
  • 淹没在空无的海洋中

    我继承的一个应用程序跟踪对材料样品执行的实验室测试结果 数据存储在单个表 tblSampleData 中 其主键为 SampleID 并有 235 列代表潜在的测试结果 问题是每个样本仅执行少量测试 因此每行包含超过 200 个空值 实际上
  • JPA 和数据库位于一个 jar 中

    我创建了一个使用 JPA 和 MySQL 的应用程序 现在我喜欢用它创建简单的桌面应用程序 例如 一个简单的 jar 最好 两个问题 在一个简单的 jar 中获取一个项目 包括它所依赖的所有 jar 的最简单方法是什么 我可以使用像 sql
  • 无法使用 Node.JS 将 null 值发送到 MySQL 数据库

    我正在尝试发送null使用 Node JS 到我的 MySQL 数据库 con query INSERT INTO Routes routeTrigger VALUES null title test function err result
  • Spring Data JPA 和 Exists 查询

    我正在使用 Spring Data JPA 使用 Hibernate 作为我的 JPA 提供程序 并想要定义一个exists附加 HQL 查询的方法 public interface MyEntityRepository extends C
  • 使用 JPAMetaModelEntityProcessor 的优点?

    我刚刚浏览了下面的链接 http hop2croft wordpress com 2011 07 07 criteria jpa 2 0 and database metamodel auto Generation with maven h
  • 跳过子级以获取父级 - JPA

    我面临一个问题 数据是递归获取的 我想避免孩子获取父数据 这导致了递归问题 我已经提到了下面的代码 Pojo结构 class Parent OneToMany mappedBy parent fetch FetchType LAZY pri
  • 我想最小化@Transactional 的范围吗?

    不确定 范围 在这里是否是正确的术语 我使用 Spring 进行 JPA 事务管理 下面有 Hibernate 我执行数据库事务的方法是私有的 但是由于您只能在类或类上设置 Transactional公共方法 http static spr
  • JPA (Hibernate) 与 OneToOnemappedBy 注释相关的问题

    当我设置一对一关系时 我有两个表 比尔和比尔简单条目 每个账单有一个 BillSimpleEntry 这是他们的结构 CREATE TABLE bill id bigint 20 NOT NULL AUTO INCREMENT PRIMAR
  • 删除指针后将其设为 NULL 是一个好习惯吗?

    我首先要说的是 使用智能指针 您将永远不必担心这个问题 下面的代码有什么问题 Foo p new Foo use p delete p p NULL 这是由答案和评论 https stackoverflow com questions 19
  • 使用 createNativeQuery 调用 Oracle 存储过程

    我需要使用 JPA 调用存储过程并找到这篇文章 http www oracle com technology pub articles vasiliev jpql html http www oracle com technology pu
  • JPA:如何在不加载延迟加载集的情况下计算子记录数

    我正在编写一个 J2EE JPA Spring 3 应用程序 试图保持纯粹的 JPA 2 0 我想获得子对象的计数而不必加载它们 因为这显然是一个昂贵的操作 例如 这是一个简化的示例 Organisation OrgID OrgName E
  • 如何模拟@PrePersist方法?

    如何模拟 PrePersist 方法 例如我实例化的实体的 preInit 我正在使用 TestNG EasyMock 是首选 Test enabled true public void testCreateOrder Instantiat
  • Eclipse 无法识别 persistence.xml 的内容

    我在 eclipse 中收到以下错误 persistence xml 文件没有可识别的内容 我的 persistence xml 文件在我的应用程序中工作得很好 但 eclipse 一直给我这个错误 我在移动文件并使用 m2eclipse
  • 空指针与 int 等价

    Bjarne 在 C 编程语言 中写道 空指针与整数零不同 但 0 可以用作空指针的指针初始值设定项 这是否意味着 void voidPointer 0 int zero 0 int castPointer reinterpret cast

随机推荐

  • Go 语言入门很简单:Go 实现简易Web应用

    前言 截止到目前为止 xff0c 几乎我们的 Go 入门文章都是在终端运行的 在终端运行的代码或者运用运用程序只适合自己在环境搭好的环境下使用 也就是说 xff0c 如果用户没有安装 Go 语言环境 xff0c 是根本没法运行我们所写的 G
  • 【待解决】使用su或sudo出现Segmentation fault

    一台服务器上 xff0c 使用sudo会出现Segmentation fault xff0c 见下 xff1a 使用root登录后 xff0c 使用su命令 xff0c 一样的会出现Segmentation fault 暂时还未找到答案 相
  • go换源|go更换国内源

    Windows 版本 SETX GO111MODULE on go env w GOPROXY 61 https goproxy cn direct SETX GOPROXY https goproxy cn direct Linux 版本
  • linux安装go环境并配置国内源

    linux安装go环境并配置国内源 第一步 官网下载安装包 https golang google cn go1 4 linux amd64 tar gz 第二步 解压缩 tar C usr local xzf go1 4 linux am
  • python - 获取时间戳(10位和13位)

    在python 开发web程序时 xff0c 需要调用第三方的相关接口 xff0c 在调用时 xff0c 需要对请求进行签名 需要用到unix时间戳 在python里 xff0c 在网上介绍的很多方法 xff0c 得到的时间戳是10位 而j
  • curl命令模拟post请求发送json格式数据

    以下代码可以作为测试接收请求的程序直接复制使用 xff1a from flask import Flask request app 61 Flask name 64 app route 39 service 39 methods 61 39
  • pip换源 -pip更换国内镜像源

    更换pip源到国内镜像 pip国内的一些镜像 阿里云 http mirrors aliyun com pypi simple 中国科技大学 https pypi mirrors ustc edu cn simple 豆瓣 douban ht
  • 使用python的requests 发送multipart/form-data 请求

    发送post请求 1 r 61 requests post 34 http pythontab com postTest 34 data 61 34 key 34 34 value 34 以上得知 xff0c post请求参数是以data关
  • SHELL - shell 脚本获取本机ip并将ip复制给变量待用

    bin bash VAR 61 34 eth0 34 HOST IP 61 ifconfig VAR grep 34 inet addr 34 awk 39 print 2 39 awk F 39 print 2 39 echo HOST
  • shell - sed匹配某一行开头,替换整行内容

    sed i 39 cloud server ip ccloud server ip 61 update skyeye 360safe com 39 name txt
  • caffe安装系列——安装cuda和cudnn

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 说明 网上关于caffe的安装教程非常多 xff0c 但是关于每一步是否操作成功 xff0c 出现了什么样的错误又该如何处理没
  • caffe安装系列——安装OpenCV

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com 说明 网上关于caffe的安装教程非常多 xff0c 但是关于每一步是否操作成功 xff0c 出现了什么样的错误又该如何处理没
  • 写递归函数的正确思维方法

    什么是递归 简单的定义 当函数直接或者间接调用自己时 xff0c 则发生了递归 说起来简单 但是理解起来复杂 因为递归并不直观 也不符合我们的思维习惯 相对于递归 我们更加容易理解迭代 因为我们日常生活中的思维方式就是一步接一步的 并且能够
  • PCL系列——拼接两个点云

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com PCL系列 PCL系列 读入PCD格式文件操作PCL系列 将点云数据写入PCD格式文件PCL系列 拼接两个点云PCL系列 从深
  • PCL系列——三维重构之移动立方体算法

    博客新址 http blog xuezhisd top 邮箱 xff1a xuezhisd 64 126 com PCL系列 PCL系列 读入PCD格式文件操作PCL系列 将点云数据写入PCD格式文件PCL系列 拼接两个点云PCL系列 从深
  • 字节(Byte)与位(bit)、十进制与二进制的关系

    一 基本常识 数据存储是以 字节 xff08 Byte xff09 为单位 xff0c 数据传输大多是以 位 xff08 bit xff0c 又名 比特 xff09 为单位 xff0c 一个位就代表一个0或1 xff08 即二进制 xff0
  • ubuntu20.04配置TensorFlow-GPU版本+对应版本的cuda&cudnn

    ubuntu20 04配置TensorFlow GPU版本 43 对应版本的cuda amp cudnn 配置说明 操作系统是Ubuntu20 04 xff0c GPU是NVIDIA GeForce RTX 2080 Ti xff0c Py
  • 十四、Rust ORM 框架

    Rust 下的 orm xff0c 之前笔者介绍过 sqlx xff0c 但使用中发现 sqlx 在进行参数绑定时 xff0c 使用的是 宏 xff0c 在当前的 IDE 生态环境下 xff0c 有时不能很好的进行代码提示 xff0c 或代
  • mybatis源码之集成mybatis-plus源码

    本文将结合源码介绍mybatis plus的原理 xff0c 包括 xff1a BaseMapper APIMybatisSqlSessionFactoryBean类BaseMapper API Statement解析Wrapper查询构建
  • Jpa 插入更新如何过滤null值

    使用Jpa时 xff0c 默认的save方法会将entity中null的值也更新到数据库 xff0c 这对与存在默认值或者更新接口将直接导致错误的记录产生 xff0c 那么如何解决这个问题 xff1f Hibernate提供了两个注解 64