SpringDataJpa set()方法自动保存失效

news2024/9/17 9:18:33

问题描述:

springdatajpa支持直接操作对象设置属性进行更新数据库记录的方式,正常情况下,get()得到的对象直接进行set后,即使不进行save操作,也将自动更新数据记录,将改动持久化到数据库中,但这里可以看到并没有生效。

问题分析:

根据问题分析可推测,大概有几种可能导致不生效:

  1. 对象不属于托管态,所以set后不生效

  1. 字段设置了@Transient注解

  1. 设置了readOnly=true,导致不生效

  1. 未flush缓存,导致不生效

    • 对象不属于托管态,所以set后不生效

首先需要了解springdatajpa自动保存的原理,这里涉及到springdatajpa中对象的几种存在状态以及jpa的缓存机制。感兴趣的可以自己详细了解一下。这里不展开说了,

Heibernate 中对象分为以下几种状态:

一、瞬时状态

瞬时状态的实体就是一个普通的java对象,和持久化上下文无关联,数据库中也没有数据与之对应。

二、托管状态

使用EntityManager进行find或者persist操作返回的对象即处于托管状态,此时该对象已经处于持久化上下文中,因此任何对于该实体的更新都会同步到数据库中。JavaBean与EntityManager发生关系后将被持久化,该Bean的任何属性改动都会牵涉到数据库记录的改动。也就是说只要我们改动这个Bean的属性,无需我们去调用其他方法,数据库的数据会自动同步。

表现为 :对 Jpa 对象进行set,但是不save,数据库也能自动更新。

三、游离状态

当事务提交后,处于托管状态的对象就转变为了游离状态。此时该对象已经不处于持久化上下文中,因此任何对于该对象的修改都不会同步到数据库中。

四、删除状态

当调用EntityManger对实体进行delete后,该实体对象就处于删除状态。其本质也就是一个瞬时状态的对象。

不同状态之间,可通过编码调用不同方法或执行相关操作触发进行转换,如刚new出来的对象是瞬时态,瞬时态可通过调用persist方法转变成托管状态,当处在托管状态的实体 Bean 被管理器 flush 了,那么就在极短暂的时间进入了持久化状态,持久态的对象属性的更改都会牵涉到数据库记录的改动。

五、持久化状态

当处在托管状态的实体Bean被管理器flush了,那么就在极短暂的时间进入了持久化状态,事务提交之后,立刻变为了游离状态。可以把持久化状态当做实实在在的数据库记录。

回到问题:

book对象为从数据库中查询得到,属于托管态,正常情况下,此时对book对象进行set操作,修改name后,应该会改变数据库中的name,但实际上执行后却并未生效。手动执行save操作后发现生效了。

第二种情况:设置了@Transient注解

查看代码可知,name字段并未设置@Transient注解

三、设置了readOnly=true,flush不刷新,导致不生效

这里需要了解jpa的缓存机制

一级缓存

Spring Data JPA的一级缓存就是当使用自定义Repositoryfind()或者findxx()方法去查询记录时,第一次会去查询数据库,然后会把查询结果存放到内存中作为缓存,后面再查询相同的记录时会直接把缓存中的结果返回,不再去查询数据库。此后对查询出来的实体进行属性修改时,均会修改缓存中的数据。

flush()方法将缓存中所有发生修改的实体的状态信息同步到数据库中。当在一个事务内通过save()方法去update一个从数据库中查询出来的实体时,Spring Data JPA并不会马上执行Update SQL语句,将修改同步到数据库,而是等到事务提交时才会通过某种机制(下面会对该机制进行描述)决定是否调用flush()方法将缓存中的实体信息同步到数据库中,当调用 flush()方法时才会执行Update SQL语句。

快照区

Spring Data JPA除了一级缓存外,还有一个快照区,当将查询结果放到一级缓存中时,会同时复制一份数据放入快照区中,Spring Data JPA通过快照区与缓存中的数据是否一致来判断数据从数据库查询出来后是否发生过修改。

Spring Data JPA在事务提交时,为了保持数据库和缓存的数据同步,会清理一级缓存并根据主键字段值判断一级缓存中的对象属性值和快照中的对象属性值是否一致,如果两个对象的属性值不一致,则调用flush()方法执行Update SQL语句,将缓存的内容同步到数据库,并更新快照;如果一致,则不调用flush()方法。

在设置了@Transactional(readOnly = true)不会进行自动flush操作

设置了@Transactional(readOnly = false)会在事务commit时触发flush方法,所以在图中第二部分执行结果中,Flushing session 在Initiating transaction commit之后

而对于手动执行flush操作的,也就是图中第三部分执行结果中,Flushing session会在Flushing session 在Initiating transaction commit之前。

Flush与事务Commit的关系

在当前的事务执行commit时会触发flush方法

在当前的事务执行完commit时,如果隔离级别是可重复度,flush之后执行的update,insert,delete的操作会被其他的新事物看到最新的结果。

假设当前的事务是可重复度,手动执行flush方法之后,没有执行commit,那么其他事务是看不到最新值的变化的。但最新值变化对当前没有commit的事务是有效的。

如果执行了flush之后,当前事务发生了rollback操作,那么数据将会被回滚(数据库的机制)

Flush的自动机制

前面讲到了当前的事务执行commit时会触发flush方法,那么除此之外还有什么情况下会自动触发flush呢?

1.事务commit之前,即指执行transactionManager.commit()之前都会触发

2.执行任何的JPQL或者nativeSQL(代替直接操作Entity的方法)都会触发flush(可以理解为不走一级缓存,所以这个时候拿到的可能是旧数据,所以在此之前需要把当前的最新改动flush到DB)

回到问题:

检查代码发现并没有设置readOnly。

4、未flush缓存,导致不生效

根据上面的排查,基本可以判断是因为没有触发flush操作,导致数据未自动更新到数据库,结合flush的刷新机制可知,事务执行commit时会触发flush方法,那么既然没有flush,说明事务有问题,这里的事务失效了,方法是使用@Postconstruct注解标识,启动后自动执行方法,这样的方式,无法通过注解方式生成代理类,事务不会生效,自然也不会触发flush操作从而导致set方法自动更新数据库记录失效。

解决办法:将方法放到service中,使用注解事务。在上层controller中去调用,保证事务生效即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/183065.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

20230126使AIO-3568J开发板在原厂Android11下跑起来

20230126使AIO-3568J开发板在原厂Android11下跑起来 2023/1/26 18:22 1、前提 2、修改dts设备树 3、适配板子的dts 4、(修改uboot)编译系统烧入固件验证 前提 因源码是直接使用原厂的SDK,没有使用firefly配套的SDK源码,所以手上这…

Linux安装mongodb企业版集群(分片集群)

目录 一、mongodb分片集群三种角色 二、安装 1、准备工作 2、安装 configsvr配置 router配置 shard配置 三、测试 四、整合Springboot 一、mongodb分片集群三种角色 router角色: mongodb的路由,提供入口,使得分片集群对外透明&…

【目标检测论文解读复现NO.27】基于改进YOLOv5的螺纹钢表面缺陷检测

前言此前出了目标改进算法专栏,但是对于应用于什么场景,需要什么改进方法对应与自己的应用场景有效果,并且多少改进点能发什么水平的文章,为解决大家的困惑,此系列文章旨在给大家解读最新目标检测算法论文,…

【工程化之路】Node require 正解

require 实现原理 流程概述 步骤1:尝试执行代码require("./1"). 开始调用方法require.步骤2:此时会得到filename,根据filename 会判断缓存中是否已经加载模块,如果加载完毕直接返回,反之继续执行步骤3&…

python图像处理(laplacian算子)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 和之前的prewitt算子、sobel算子不同,laplacian算子更适合检测一些孤立点、短线段的边缘。因此,它对噪声比较敏感,输入的图像一定要做好噪声的处理工作。同时,laplacian算子设计…

Leetcode 03. 无重复字符的最长子串 [C语言]

目录题目思路1代码1结果1思路2代码2结果2该文章只是用于记录考研复试刷题题目 Leetcode 03: 给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。 示例 1: 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所…

尚医通-OAuth2-微信登录接口开发(三十一)

目录: (1)微信登录-OAuth2介绍 (2)前台用户系统-微信登录-准备工作 (3)微信登录-生成微信二维码-接口开发 (4)微信登录-生成验证码-前端整合 (5&#xf…

Telerik DevCraft Ultimate R1 2023

Telerik DevCraft Ultimate R1 2023 Kendo UI R1 2023-添加新的Chip和ChipList组件。 KendoReact R1 2023(v5.11.0)-新的PDFViewer组件允许用户直接在应用程序中查看PDF文档。 Telerik JustLock R1 2023-Visual Studio快速操作菜单现在可以在创建通用…

蓝桥杯重点(C/C++)(随时更新,更新时间:2023.1.29)

点关注不迷路,欢迎推荐给更多人 目录 1 技巧 1.1 取消同步(节约时间,甚至能多骗点分,最好每个程序都写上) 1.2 万能库(可能会耽误编译时间,但是省脑子) 1.3 蓝桥杯return 0…

【数据库-通用知识系列-01】数据库规范化设计之范式,让数据库表看起来更专业

我们在设计数据库时考虑的因素包括读取性能,数据一致性,数据冗余度,可扩展性等,好好学习数据库规范化的知识,设计的数据库表看起来才专业。 范式一览 “键”理解: 超键:在关系中能唯一标识元组…

送什么礼物给小学生比较有纪念意义?适合送小学生的小礼物

送给小学生的礼物哪种比较有意义呢?送给学生的礼物,基本上是对学习有所帮助的,但是像送钢笔、练习册这些,有一部分学生是抗拒的,作为大人就是希望对视力、对成长有用的东西,我认为保护视力是现在许多家庭的…

isNotEmpty() 和 isNotBlank() 的区别,字符串判空, StringUtils工具包 StringUtil工具类,isEmpty() 和 isBlank() 的区别

目录1.StringUtils 和 StringUtilStringUtils 的依赖:StringUtils 的用法:StringUtil 工具类2. isNotEmpty() 和 isNotBlank()1.StringUtils 和 StringUtil 注:StringUtils 和 StringUtil 的区别(StringUtil为自定义工具类&#…

以表达式作为template参数

目录 一.template参数的分类&#xff1a; 二.非类型参数与默认参数值一起使用 三.应用 一.template参数的分类&#xff1a; ①.某种类型&#xff1a; template<typename T>; ②.表达式(非类型)&#xff1a; template<int length,int position>; 其中length…

Liunx中shell命令行和权限的理解

文章目录前言1.shell外壳的理解2.关于权限理解1.Linux下的用户2.角色划分3.文件和目录的权限3.粘滞位3.总结前言 Linux中的操作都是通过在命令行上敲指令来实现的&#xff0c;本文将简单的介绍Linux中的外壳程序shell以及浅谈一下对Linux中的权限理解。 1.shell外壳的理解 Lin…

微信小程序开发(一)

1. 微信小程序的开发流程 2. 注册小程序 小程序注册页&#xff1a;https://mp.weixin.qq.com/wxopen/waregister?actionstep1 如已注册&#xff0c;直接登录 小程序后台 https://mp.weixin.qq.com/ 即可。 在小程序后台的 【开发管理】→ 【开发设置】下可以查看AppID&…

算法训练营DAY45|322. 零钱兑换、279.完全平方数

两道题思路上有相似之处&#xff0c;都是求得最少的种类方法&#xff0c;也就是说在完全背包里给定容量时&#xff0c;用最少的物品去装满背包。它和用最多的方法去装满背包也有一些相似&#xff0c;也就是说两者实际上是互通的。 322. 零钱兑换 - 力扣&#xff08;LeetCode&a…

HTML零散知识

1、代码规范与思路 参考凹凸实验室代码规范&#xff1a;Aotu.io - 前端代码规范 CSS编写顺序的思路 先确定盒子本身是如何布局 position: absolutefloat: left/rightdisplay: flex 盒子的特性和可见性 display: block/inline-block/inline/nonevisibility/opacity 盒子模型…

【Pytorch项目实战】之生成式模型:DeepDream、风格迁移、图像修复

文章目录生成式模型&#xff08;算法一&#xff09;深度梦境&#xff08;DeepDream&#xff09;&#xff08;算法二&#xff09;风格迁移&#xff08;Style Transfer&#xff09;&#xff08;算法三&#xff09;图像修复&#xff08;Image Inpainting&#xff09;&#xff08;一…

(13)工业界推荐系统-小红书推荐场景及内部实践【用户行为序列建模】

&#xff08;1&#xff09;工业界推荐系统-小红书推荐场景及内部实践【业务指标、链路、ItemCF】 &#xff08;2&#xff09;工业界推荐系统-小红书推荐场景及内部实践【UserCF、离线特征处理】 &#xff08;3&#xff09;工业界推荐系统-小红书推荐场景及内部实践【矩阵补充、…

Docker搭建LNMP+Wordpress

一、服务器环境 容器操作系统IP地址主要软件nginxCentOS 7172.18.0.10Docker-NginxmysqlCentOS 7172.18.0.20Docker-MysqlmysqlCentOS 7172.18.0.20Docker-Mysql 二、Linux系统基础镜像 systemctl stop firewalld setenforce 0 docker pull centos:7 #从公有仓库中下载cento…