日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring Data JPA 禁止自动更新

發布時間:2024/7/23 javascript 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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

總結

以上是生活随笔為你收集整理的Spring Data JPA 禁止自动更新的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。