文章目录

  • 一。背景介绍
  • 二。Spring JPA相关介绍
    • 2.1 JPA中Entity的各种状态
    • 2.2 EntityManager自动update数据库的原因
    • 2.3 关于自动更新的EntityManager的三个关键方法
    • 2.4 如何避免自动更新

一。背景介绍

最近公司项目在进行回归测试时发现,金额结算模块的数据老是会自动update成相反的负数,但是相关接口没有任何取反的代码,并且存到数据库第一时间都是正数,是过了一会自动被update成负数。一开始还以为有人写了相关的SP(存储过程),会不定时将金额取反,但是后面问了很多同事都没有说有写过类似的SP。找了很久之后发现,Spring JPA框架的session问题会导致将该实体进行赋值Set操作时同时也会自动update数据库,这就导致了自动更新数据库的问题。虽然在计算金额的接口没有涉及到任何的update或者实体的set代码,但是当其他接口有这些代码,当你调用这个接口的时候,由于你的entity还属于session管理的状态,进行了set操作,所以不管你最后是否会调用JPA Update相关的方法,最后entityManager都会将你重新set的值自动update到数据库中。

二。Spring JPA相关介绍

2.1 JPA中Entity的各种状态

  • 临时(新建)状态:对象被创建时的状态,数据库里面没有与之对应的记录!也就是没有保存到数据库之前的状态。
  • 持久(托管)状态:处于session的管理中,并且数据库里面存在与之对应的记录!
  • 游离(脱管)状态:对象不处于session的管理中,但是数据库里面存在与之对应的记录!
  • 删除状态:数据库中没有,Session缓存中没有。

2.2 EntityManager自动update数据库的原因

因为当实体对象属于托管状态下时,往这个对象里面的某个属性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管理了,任何对此对象的状态变更也将不会被同步到数据库。

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

merge
通过entityManager将一个存在的实体“同步到”persistenceContext中。实体的状态将从其单独的状态转换为受persistenceContext管理的状态。如果Entity是新创建的,则这个方法类似于persist()这个方法。如果Entity已经存在的,则只作为更新操作。

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

Refresh
Refresh的作用是从数据库中将Entity的状态进行更新操作。如果Entity和数据库中的数据不一致,将更新数据库中的数据到Entity中。数据由数据库到缓存,但在commit或flush之前调用Refresh,那么缓存中的数据又变成了和数据库中的数据一样的了,你原先修改的数据白费了

2.4 如何避免自动更新

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) 这样就可以了。

解决Spring JPA自动更新数据库的问题相关推荐

  1. jPA自动创建数据库表的一些配置

    2019独角兽企业重金招聘Python工程师标准>>> jPA自动创建数据库表的一些配置 hibernate.cfg.xml 中hibernate.hbm2ddl.auto配置节点如 ...

  2. python更新pip失败-解决Python pip 自动更新升级失败的问题

    在使用python pip的时候,经常会发生pip版本过低导致失败的情况,这时候,系统会提示让你使用如下命令对pip进行升级更新: python -m pip install --upgrade pi ...

  3. day35-hibernate映射 03-Hibernate持久态对象自动更新数据库

    持久态对象一个非常重要的能力:自动更新数据库. package cn.itcast.hibernate3.demo1;import static org.junit.Assert.*;import o ...

  4. Code First 下自动更新数据库结构(Automatic Migrations)

    示例 Web.config <?xml version="1.0" encoding="utf-8"?> <configuration> ...

  5. win10系统打开更新服务器失败怎么回事,如何修复Windows Update组件以解决Win10无法自动更新的问题?...

    如何修复Windows Update组件以解决Win10无法自动更新的问题?老司机都知道Win10的自动更新机制是通过Windows Update相关组件的正常运作来实现的,如果Windows Upd ...

  6. ef mysql自动更新_EntityFrameworkCore使用Migrations自动更新数据库

    EntityFrameworkCore使用Migrations自动更新数据库 系统环境:Win10 IDE:VS2017 RC4 .netcore版本:1.1 一.新建ASP.NET Core Web ...

  7. 计算机策略更新失败怎么办,大神教你解决win10系统自动更新安装失败的途径

    许多win10系统用户在工作中经常会遇到win10系统自动更新安装失败的情况,比如近日有用户到本站反映说win10系统自动更新安装失败的问题,但是却不知道要怎么解决win10系统自动更新安装失败,我们 ...

  8. 更新wpscan_解决新版wpscan无法更新数据库问题

    在做一个靶机时需要用到wpscan,然后以前学习wp漏洞的时候也有看过,但是没有强制性需要,就没管了,所以这次就想着必须给解决掉.ps:这个解决了,靶机wp马上就出来了 在网上百度了一大堆方法都不行, ...

  9. 解决Spring JPA删除方法报错问题

    JPA删除方法报错 org.springframework.dao.InvalidDataAccessApiUsageException: Executing an update/delete que ...

最新文章

  1. Java集合框架:ArrayList
  2. php同步邮件,php – 使用同步驱动程序在Laravel 4中排队电子邮件
  3. 程序员“不会”修电脑的原因
  4. back propagation反向传播(浅层神经网络分析示例)
  5. OC中方法与函数的区别
  6. HDFS的shell命令
  7. Unity导入中文文本的解决方法
  8. PageHelper.startPage分页失效问题,亲测已解决
  9. Qt开发笔记之编码h264码流并封装mp4(六):ubuntu平台编译mp4v2并封装mp4
  10. 清理服务器系统日志,win2008服务器清理系统日志
  11. [4G5G专题-78]:流程 - 4G LTE 核心网的Attach流程
  12. 微信扫码关注登录(vue+node+express+mongodb)
  13. PS4手柄控制无人驾驶小车车
  14. 天图投资境外上市获批:上半年营收降​18% 投了小红书与百果园
  15. laydate时间控件 (开始日期、结束日期)
  16. beanmapper java_Java今日收获——BeanMapper
  17. SpringMVC——文件上传下载,异步请求和SSM整合
  18. java实现麻将(集合的应用)
  19. 小程序授权登录流程详情步骤
  20. w7系统计算机e盘无法打开,win7系统拒绝访问磁盘该的解决方法?

热门文章

  1. Flutter 单元测试
  2. find命令 tpye选项
  3. MUR860D-ASEMI快恢复二极管MUR860D参数
  4. 【Wikipedia爬虫工具包的使用】请求超时、代理错误、SSLError
  5. 《小学生四则运算出题软件》结对项目总结
  6. World Locking Tools for Unity Sample (二)QR Space Pins
  7. 猜字母 把abcd...s共19个字母组成的序列重复拼接106次,得到长度为2014的串。
  8. android平铺动画,Android实现平铺图片效果
  9. 数据人该知道的埋点体系(二)
  10. 联想电脑预装系统的激活工具