Spring Data JPA 禁止自动更新

公司的项目后台架构是SpringBoot + Spring Date JPA,采用MySQL数据库。在工作刚开始时就遇到了一个奇怪的现象。在采用Date JPA查询完数据库之后,若改变了查询出的对象属性,那么数据库就会自动更新。比如查询出一个studentPO的name为“小明”,然后进行了一步studentPO.setName("小红")操作,再返回给前台,此时的数据库中的这个studentPO的name就会自己变成小红。但是我并没有调用updateBean方法去主动的更新这个对象,为什么它就会自动更新了呢?

起初我以为这个是和JPA的缓存有问题,就类似于Hibernate的缓存机制一样为了要和数据库保持一致。最近有空了,研究后才发现并不是缓存的原因,而是和对象的状态有关。

首先我们先来了解一下Spring Date JPA:

1、Spring-data-jpa的基本介绍

Spring Data JPA是更大的Spring Data系列的一部分,可以轻松实现基于JPA的存储库。此模块处理对基于JPA的数据访问层的增强支持。它使构建使用数据访问技术的Spring驱动应用程序变得更加容易。

在相当长的一段时间内,实现应用程序的数据访问层一直很麻烦。必须编写太多样板代码来执行简单查询以及执行分页和审计。Spring Data JPA旨在通过减少实际需要的工作量来显着改善数据访问层的实现。作为开发人员,您编写存储库接口,包括自定义查找器方法,Spring将自动提供实现。

2、spring data jpa 数据库自动更新

再来了解一下对象有哪些状态

2.1 对象的状态:

 (一) 临时(新建)状态:对象被创建时的状态,数据库里面没有与之对应的记录!也就是没有保存到数据库之前的状态。

 (二) 持久(托管)状态:处于session的管理中,并且数据库里面存在与之对应的记录!

 (三) 游离(脱管)状态:对象不处于session的管理中,但是数据库里面存在与之对应的记录!

   (四) 删除状态:数据库中没有,Session缓存中没有。

2.2 自动更新的原因:

因为当实体对象属于托管状态下时,往这个对象里面的某个属性set新的值,这个新的值会被自动更新到数据表中去。(JPA自带的特性)

如何判断对象是否处于托管状态:

使用EntityManager.contains(entity)方法可以得知某个实体对象是否处于托管状态,也就是说是否处于persistence context中。

EntityManager:是JPA中用于增删改查的接口,它的作用相当于一座桥梁,连接内存中的java对象和数据库的数据存储

persistence context:是由一组受托管的实体对象实例所构成的集合。它受entity manager 的管理。Entity manager追踪persistence context中所有对象的修改和更新情况,并根据指定的flush模式将这些修改保存到数据库中。一旦persistence context被关闭,所有实体对象实例都会脱离EntityManager而成为非托管对象。对象一旦从persistence context中脱离,就不再受entity manager管理了,任何对此对象的状态变更也将不会被同步到数据库。

关于自动更新的EntityManager的三个关键方法:

1.merge

通过entityManager将一个存在的实体“同步到”persistenceContext中。

实体的状态将从其单独的状态转换为受persistenceContext管理的状态。

如果Entity是新创建的,则这个方法类似于persist()这个方法。

如果Entity已经存在的,则只作为更新操作。

2.Flush

将PersistenceContext的信息同步到数据库中。

当触发Flush这个动作的时候,所有的实体都将会被insert/update/remove到数据库中。会强制发送sql更新(update)语句,数据由内存到数据库

flush触发的时间:当对缓存中的数据进行一系列操作后,一般提交事务时,会调用flush方法,把数据库更新一下
3.Refresh

Refresh的作用是从数据库中将Entity的状态进行更新操作。如果Entity和数据库中的数据不一致,将更新数据库中的数据到Entity中。数据由数据库到缓存

 
但在commit或flush之前调用Refresh,那么缓存中的数据又变成了和数据库中的数据一样的了,你原先修改的数据白费了

2.3 如何避免自动更新 

1、事务提交之前调用Refresh(不推荐)

改变后的内存中的PO在Refresh之后又变得和数据库一模一样,然后再在事务提交之后调用flush方法,将数据从内存中更新到数据库(好像这样做没多大意义)。

2、set 属性前,将其状态改为游离状态。

将处于persistence context范围中的托管对象变为游离对象,这时重置属性值不会更新到数据表中去。

persistence context 有两种类型。一种称为 transaction-scope persistence context,在这种状态下 persistence context 是与事务相关的,也就是说在事务范围内托管对象所有的更改都会被更新到数据表中去,当事务提交后,这个 persistence context 也就销毁了,之后的更改不会被更新到数据表中去。另一种为 extended persistence context

一般使用的 persistence context 都是默认的 transaction-scoped,extended 的很少用到。

3、避免直接修改查询出的PO对象(我们项目使用的方法)

其实在标准的项目中都存在一个POJO包,我们项目中使用的是VO和PO,比如建立一个StudentPO和一个StudentVO,两个对象的属性完全一样,查询出PO后,将PO对象转为VO对象,然后再去对VO对象进行操作。

将对象置为游离态的方法:

close 方法:关闭 session 这样这个对象肯定是游离态了,因为 session 已经关闭了,但是往往我们实际的开发过程中,session 在后面是要用的到的,所以这个方法可行,但是不一定用得上,分清具体的情况。

clear 方法:将 session 中的所有的对象全部清除出缓存,这个方式有点劳师动众,不过 session 清除了全部的对象之后自然就会变为游离态了,这样做不是很好。

evict 方法:将某一个对象清除出缓存 session,这个方法是很好的实现方式,推荐使用。调用的时候是这样的,session.evict(Object obj) 这样就可以了。

3、自动更新的应用和好处

这个暂时没找到。。。。。。

4、总结

因持久层框架自身的机制,会在事务提交后会将托管状态的对象自动更新到数据库,如果要想避免自动更新,就可以在事务提交之前将对象状态强制置为非托管状态
————————————————
版权声明:本文为CSDN博主「你的小祖宗饿了」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_38658642/article/details/90729827

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

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

相关文章

Nature:寻找记忆的痕迹

来源:神经科技对于不是《神探夏洛克》超级粉丝的人来说,认知神经科学家Janice Chen对这部英国广播公司的热播侦探剧的了解比大多数人多。当观众观看这部电视剧的第一集然后描述其情节时,Chen能在脑部扫描仪的帮助下监视他们的脑子里正在发生什…

tcl linux 刷 安卓系统,安卓用户看过来—手把手教你刷第三方系统

来来来,小葵花课堂讲课啦。孩子咳嗽老不好,多半是废了,打一顿就好。手机卡顿老不好,先别着急,来刷个机吧。众所周知,因为安卓系统自身的特性,安卓手机用久了难免出现卡顿。一般来说解决的方法有…

DeepMind开源Psychlab平台——搭建AI和认知心理学的桥梁(附论文和代码下载)

来源:专知概要:DeepMind近期开源了Psychlab,这是一个利用认知心理学等领域知识来研究受控环境下人工智能体(Artificial Agent)的行为,从而模拟人类的行为。DeepMind近期开源了Psychlab,这是一个…

linux启动过程剖析,分析Linux系统的启动过程

导读一直使用linux系统,却对系统启动过程及系统初始化和各种服务的启动不太清楚。今天终于搞明白整个是怎么一回事了。本来想自己写篇文章,刚好在网上看到一篇不错的介绍,很详细,就直接拿来了。Linux系统的启动过程:BI…

扩展立方体 The Scale Cube

转自: https://akfpartners.com/growth-blog/scale-cube/ 比例立方体 2018年4月25日| 发布者:Robin McGlothin Scale Cube是用于定义微服务和扩展技术产品的模型。AKF Partners于2007年发明了Scale Cube,最初于2007年在我们的博客上在线发…

人脑动态功能网络连接模式能够鉴别个体并预测其认知功能

来源:神经科技概要:近二十年来,基于静息态功能磁共振影像的人脑连接组学快速发展,为无创研究活体人脑的功能组织规律和网络运作机制提供了重要手段,大大促进了研究者对脑认知、脑发育和脑疾病神经机制的理解。近日&…

linux中dhcp如何配置两个子网,linux – 配置DHCP服务器以在同一VLAN上为多个子网提供服务...

我有一个由多个子网组成的VLAN,我想使用DHCP集中IP地址指定.DHCP服务器(100.100.25.88)是子网100.100.25.64/27上的Debian计算机.我想为子网100.100.68.0/24中的计算机分配IP地址.最终目标是在100.100.68.0/24子网中的所有计算机上启用PXE引导.下面是我的dhcpd.conf文件,# DHCP…

JMS之企业消息传送

企业消息传送:消息是通过网络从一个系统异步传送给其他系统的。 客户端:使用消息传送API 的一个业务应用程序或组件(如:JMS) 集中式体系结构 分散式体系结构

linux看系统硬件,Linux 查看系统硬件信息(实例详解)

cpulscpu命令,查看的是cpu的统计信息.blueblue-pc:~$lscpuArchitecture:i686#cpu架构CPUop-mode(s):32-bit,64-bitByteOrder:LittleEndian#小尾序CPU(s):4#总共cpulscpu命令,,查看的是cpu的统计信息.blueblue-pc:~$ lscpuArchitecture:i686#c…

达沃斯群英纵论人工智能,核心观点汇总

来源:AI科技大本营概要:一年一度的世界经济论坛年会(达沃斯论坛)上,来自不同领域的精英纷纷发表了自己对于人工智能的看法。一年一度的世界经济论坛年会(达沃斯论坛)已经召开了3天,该…

Java消息服务思维导图笔记

https://www.processon.com/view/link/610b5f201efad40724bdfae2

window计算的chk在linux下可以读,Linux系统命令从入门到完全忘记(四)

系统安全相关命令chmod概要:用于改变文件或目录的访问权限,用它控制文件或目录的访问权限。语法格式:chmod [-cfvR] [–help] [–version] mode file参数:参数说明-c当发生改变时,报告处理信息-f错误信息不输出-R处理指…

如何设计一个安全对外的接口

来源:https://mp.weixin.qq.com/s/eDXsqyfIKDXii0DB6W0UcA

三大国有银行同时入股 AI 公司第四范式

来源:新华社概要:人工智能公司第四范式于1月26日宣布完成B+轮融资,并同时宣布获得来自中国工商银行、中国银行、中国建设银行三家国有银行及所属基金的联合战略投资。人工智能公司第四范式于1月26日宣布完成B+轮融资&a…

freedos能够编译c语言嘛,Freedos freedos核心源代码包含汇编和C语言代码 - 下载 - 搜珍网...

Freedos 内核源代码Freedos 内核源代码/KE2035AFreedos 内核源代码/KE2035A/BINFreedos 内核源代码/KE2035A/BIN/AUTOEXEC.BATFreedos 内核源代码/KE2035A/BIN/CONFIG.SYSFreedos 内核源代码/KE2035A/BIN/INSTALL.BATFreedos 内核源代码/KE2035A/BOOTFreedos 内核源代码/KE2035…

关于DataAccess Application block

这几天好好的看了一下MS的DataAccess Application block。也试着自己实现了一个。发现它在Parameter的缓存方面,储存过程确实做得不错,但是对于一般Sql语句(CommandType.Text)的查询来说,参数的缓存就显得比较麻烦。有…

Java中的时区转换

转载自 halfclear 原文:https://blog.csdn.net/halfclear/article/details/77573956 1.Date中保存的是什么 在java中,只要我们执行 Date date new Date(); 就可以得到当前时间。如: Date date new Date(); System.out.println(date);12 输…

从语言学到深度学习NLP,一文概述自然语言处理

来源:萤火虫沙龙2概要:自然语言处理(NLP)近来因为人类语言的计算表征和分析而获得越来越多的关注。自然语言处理(NLP)近来因为人类语言的计算表征和分析而获得越来越多的关注。它已经应用于许多如机器翻译、…

中国石油大学华东c语言答案全集,【2019年整理】中国石油大学华东C语言习题答案.pdf...

C 语言复习题【设计型】5.1 输出一行星号编写程序在一行中输出 N 个星号。输入&#xff1a; N 值输出&#xff1a; 一行中 N个星号#includeint main(){int a,i;scanf("%d",&a);for(i1;i<a;i)printf("*");printf("\n");return 0;}【设计型…

特老的文章:三层应该怎么划分。不知大家还有用否

可以用这样的思想&#xff1a; 最初的应用是单机&#xff0c;数据和功能都放在一台机器上。随着应用向工作组模式发展中&#xff0c;人们迫切需要 调用彼此的数据&#xff0c;也调用彼此的功能&#xff0c;这样人们就不用重复录入数据&#xff0c;程序员也不须重复写 功能。数据…