公司的项目后台架构是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

Spring Data JPA 禁止自动更新相关推荐

  1. datav本地部署 java,Spring Boot对Spring Data JPA的自动配置

    一 点睛 Spring Boot对Spring Data JPA的自动配置放置在如下路径: 二 源码分析 1 JpaRepositoriesAutoConfiguration类分析 @Configur ...

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

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

  3. Springboot整合Spring Data JPA

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

  4. Spring Data JPA 与 MyBatis 对比,你喜欢用哪个?

    来源:jianshu.com/p/3927c2b6acc0 概述 Spring Data JPA是Spring Data的子模块.使用Spring Data,使得基于"repositorie ...

  5. Spring Data Jpa 实体类自动创建数据库表失败解决

    先说一下我遇到的这个问题,首先我是通过maven创建了一个spring boot的工程,引入了Spring data jpa,结果实体类创建好之后,运行工程却没有在数据库中自动创建数据表. 找了半天发 ...

  6. 关于spring data jpa 仓储层自动实现

    Spring Data JPA: Spring提供的一个用于简化JPA开发的框架 Spring Data JPA不需要过多的关心Dao层的实现,只需关注我们继承的接口,按照一定的规则去编写我们的接口即 ...

  7. Spring Data JPA使用必备(二):Spring Data JPA方法命名规则实现SQL自动生成

    Spring data JPA是一个好东西,但是对于很多习惯于写SQL,直接怼数据库的人来说,这个真的用不习惯,还被一致认为是一个不易于程序员发展的技术.因为JPA提供了标准的封装,在操作数据库的时候 ...

  8. Spring Boot整合Spring Data JPA操作数据

    一. Sping Data JPA 简介 Spring Data JPA 是 Spring 基于 ORM 框架.JPA 规范的基础上封装的一套 JPA 应用框架,底层使用了 Hibernate 的 J ...

  9. Spring Data JPA 五分钟快速入门和实践

    Spring Data JPA(类似于Java Web 中的 DAO) 操作声明持久层的接口(Repository) 三个核心接口: CrudRepository PagingAndSortingRe ...

最新文章

  1. c++ 虚函数_到底什么情况下会合成默认构造函数?
  2. I/O异步之I/O完成端口
  3. python aes_python AES 加密
  4. 另一个日历(根据农历网上的寿星万年历修改)最新修改适应FF
  5. java 在底图上绘制线条_使用底图和geonamescache绘制k表示聚类
  6. 前端学习(2231):react条件渲染之列表渲染
  7. DEP机制的保护原理
  8. 如何在spring框架中解决多数据源的问题[转]
  9. 计算机硬件的基本结构和工作原理
  10. dbf转成excel_dbf转换成excel下载|dbf转换成excel v1.0-520下载站
  11. 电力系统继电保护Matlab实验,电力系统继电保护原理及仿真
  12. 构建Spring Cloud项目找不到Application类
  13. 开放电脑站点81端口
  14. postgresql注册表删除_彻底删除SQL Server注册表的方法
  15. Unity 之 ShaderGraph 实现火焰效果入门级教程
  16. unity material以及各种贴图介绍
  17. 小学生必积累的名人名言汇总100条
  18. 低通滤波器的一阶RC电路模型
  19. 集团化企业的电子印章管理模式
  20. Charles抓包APP

热门文章

  1. 论文小综 | 文档级关系抽取方法(上)
  2. 论文浅尝 - ACL2020 | 用于多媒体事件提取的跨媒体结构化公共空间
  3. 论文浅尝 | 利用指针生成网络的知识图谱自然语言生成
  4. CNN卷积神经网络(吴恩达《卷积神经网络》笔记一)
  5. 十大双跨平台整体发展情况盘点
  6. Exploiting the Syntax-Model Consistency for Neural Relation Extraction(关系抽取,语法模型,跨领域关系抽取
  7. @Controller与@RestController的区别以及ircular view path [ad]: would dispatch back to the current handler异常
  8. Leetcode905.Sort Array By Parity按奇偶排序数组
  9. C++ primer 4th 第10章《关联容器》总结
  10. Tensorflow深度学习应用(筑基篇)