【java框架】JPA(2) -- JPA基礎

来源:https://www.cnblogs.com/yif0118/archive/2020/05/01/12815316.html
-Advertisement-
Play Games

1. JPA核心API對象 1.1.Persistence持久化對象 Persisitence主要用於創建EntityMangerFactory,它可以根據傳入的持久化單元名稱來創建對應的EntityMangerFactory。 // 對應配置文件裡面的persistence-unit name=" ...


1.   JPA核心API對象

1.1.Persistence持久化對象

Persisitence主要用於創建EntityMangerFactory,它可以根據傳入的持久化單元名稱來創建對應的EntityMangerFactory。

// 對應配置文件裡面的persistence-unit name="cn.yif.jpa02"
// 通過持久化類創建一個實體類管理工廠
EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("cn.yif.jpa02");

1.2.EntityMangerFactory實體管理工廠

EntityMangerFactory是一個線程安全的對象,在一個項目中只需要一個EntityManger對象,對應一個資料庫資源,EntityMangerFactory對象是一個重量級對象,創建與銷毀是比較耗費資源的,其中包含了資料庫的配置信息,所有實體及關係,預定義JPQL語句、二級緩存。

1.3.EntityManger實體管理對象

EntityManger提供和持久化相關的操作:包括增、刪、改、查等,是線程不安全的對象,因此在項目中應該每次只能讓一個線程所使用,避免多個線程共用使用。EntityManger是輕量級的,創建與銷毀不需要消耗太多的資源,應該用完就關閉。Web中對應一次請求,創建一個EntityManger對象。

1.4.Transcation事務

分為javax.persistence.EntityTransaction與javax.transaction.Transaction JTA事務兩種。

javax.persistence.EntityTransaction:只能控制相同一個資料庫不同表的事務管理,大多數情況使用這種。

 

javax.transaction.Transaction:處理不同資料庫不同表的事務管理。Tomcat預設不支持JTA事務(可以通過插件來解決),或者需要用JavaEE伺服器:如jboss、weblogic伺服器。

JTA事務使用場景:比如跨行轉賬、事務列表。

2.   主鍵生成策略

主鍵實現有兩種類型,分為:自然主鍵與代理主鍵。

自然主鍵:表示把含有業務意義的欄位作為主鍵,一般比如使用身份證號、手機號等作為自然主鍵,而且此欄位必須唯一。

註意:在JPA中不定義@GeneratedValue則表示自然主鍵,在保存之前自己設置主鍵值。

 

代理主鍵:主鍵一般沒有任何意義,用來區別每行數據是不同的。

在JPA中提供了四種主鍵生成的策略:IDENTITY、SEQUENCE、TABLE、AUTO。

2.1.IDENTITY

IDENTITY表示主鍵自增,JPA配置IDENTITY策略時會自動將主鍵設置為自增+1,具體配置如下:

//@Id是必須的註解,表示對應資料庫的主鍵
   @Id
   //GeneratedValue表示主鍵生成策略
   //①IDENTITY:表示的是自增,
   // 特點:1.主鍵必須是數值類型;2.使用的資料庫必須支持自增功能;3.使用資料庫原生的生成策略,性能是很高的
   // 4.支持IDENTITY的資料庫類型:MySQL, SQL Server, DB2, Derby, Sybase, PostgreSQL
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Integer id;

2.2.SEQUENCE

SEQUENCE表示自增方式為序列方式,一般在Oracle中使用,一個Domain創建一張表,對應一個序列,Oracle不支持ID自增長列而是使用序列機制生成主鍵ID。

//②SEQUENCE:序列
    //特點:1.主鍵必須是數值類型;2.使用的資料庫必須支持序列;3.使用資料庫原生的生成策略,性能上是很高的
    //4.會預設去創建一個序列,這個序列的名稱叫做:HIBERNATE_SEQUENCE,所有Domain都預設使用這個序列,ID在這個序列基礎上自增
    //使用名叫SEQ特定的序列
    @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "SEQ")
    //name:序列生成器的名稱,會在@GeneratedValue中進行引用
    //sequenceName會對應真實資料庫中序列的名稱OIDDOMAIN_SEQUENCE,在資料庫中創建名稱為OIDDOMAIN_SEQUENCE的序列
    //如果不指定序列生成器的名稱sequenceName = "OIDDOMAIN_SEQUENCE",
    //則使用廠商提供的預設序列生成器,比如Hibernate預設提供的序列名稱為HIBERNATE_SEQUENCE
    @SequenceGenerator(name = "SEQ", sequenceName = "OIDDOMAIN_SEQUENCE")
    private Integer id;

支持SEQUENCE的資料庫:Oracle、Post greSQL、DB2。

2.3.TABLE

TABLE支持所有的資料庫類型,在實際項目中如果前期確定不了資料庫,可以使用TABLE。

//③TABLE(高低位)
    //特點:1.主鍵必須是數值類型;2.支持所有的資料庫類型(使用預設的序列);3.性能超級低,每次使用都要進行查詢與修改(相容性犧牲)
    //如果不使用表生成器,會使用預設的表,比如Oracle中使用HIBERNATE_SEQUENCE
    @TableGenerator(name = "SEQ", table = "OidDomain_TABLE", pkColumnName = "SEQUENCE_NAME", valueColumnName = "SEQUENCE_COUNT", initialValue = 1, allocationSize = 1)
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "SEQ")
    private Integer id;

2.4.AUTO

//④AUTO 自動根據具體的資料庫選擇合適的策略,可以是TABLE/SEQUENCE/IDENTITY中的一種
   //假如資料庫是Oracle,則選擇顯示配置Sequence,不使用預設序列配置
   //假如資料庫是MySQL,則選擇Identity
   //如果不特別指定,這是預設的主鍵生成策略
   @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

3.   JPA持久對象狀態

JPA中有四種持久化對象的狀態:臨時狀態(transient):瞬時狀態、持久化狀態(persistent):托管狀態、游離狀態(detached):脫管狀態、刪除狀態(removed)。

臨時狀態:表示該對象剛剛使用new語句創建,沒有和EntityManager發生關係。沒有被持久化,不處於EntityManager中。

持久化狀態:表示該對象和EntityManager發生了關係,被加入到EntityManager的一級緩存中,一級緩存中有數據了。

游離狀態:這個對象和EntityManager解除了關係,已經被持久化,但不處於EntityManager中。

刪除狀態:調用了EntityManager.remove()方法,對象有關聯的ID,並且在EntityManager的管理下,可能計劃被刪除,事務被commit提交後真正刪除。

3.1.臟數據更新

臟數據:一個持久化對象在事務管理內,發生在事務訪問數據並對數據進行了修改,但還未提交到資料庫中,未提交的這個數據就叫做臟數據。

而臟數據在JPA中執行merge時,與是否調用merge方法無關,此時當事務進行提交commit時,會自動更新到資料庫中。

@Test
    public void JPAUpdate() {
        EntityManager entityManager = JPAUtil.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();
        //從資料庫中拿到的對象是一個持久化的對象
        Employee employee = entityManager.find(Employee.class, 1);
        employee.setName("修改者哈哈");
        employee.setAge(223);
        //執行修改
        //在對象是持久化對象的狀態下,用不用merge方法,和修改沒有關係,即調用與否,都會向資料庫做修改
        //entityManager.merge(employee);
        //提交的時候會從資料庫查詢有沒有這個employee,如果變更了,就執行merge進行數據更新
        //即commit的時候才執行sql,這個過程叫做臟數據更新(一旦持久化數據對象進行修改,就是臟數據)
        transaction.commit();

        JPAUtil.close(entityManager);
}

3.2.臟數據更新執行流程

①    拿到entityManager對象,開啟事務;

②    通過entityManager對象從資料庫中查詢到對應的持久化對象,這個對象會放入到一級緩存中,JPA會為當前的這個對象準備一個快照(相當於把這個對象進行一個備份);

③    在提交事務之前,JPA會將當前這個快照對象與資料庫中查詢到的對象做一個對比,如果相同,就不需要進行修改了,也不會發送對應的merge SQL進行修改;如果對比發現不同,那麼JPA就會認為現在這個數據是臟數據,臟數據在事務進行提交的時候,發送merge SQL語句進行資料庫數據的同步。

3.3.Persist與Merge對比

@Test
    public void JPAPersistOrMerge() {
        Employee employee = new Employee("創建者001", 20);
        EntityManager entityManager = JPAUtil.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();
        /**
         *  persist:放到方法中的對象會變成持久化對象,改變的是原對象(這個對象就在一級緩存當中)
         */
        entityManager.persist(employee);
        employee.setName("更新創建者001");
        transaction.commit();
        JPAUtil.close(entityManager);
    }

對應會執行兩條SQL語句:先發送insert語句,之後發送update語句進行臟數據更新。

 

 

@Test
    public void JPAPersistOrMerge() {
        Employee employee = new Employee("創建者001", 20);
        EntityManager entityManager = JPAUtil.getEntityManager();
        EntityTransaction transaction = entityManager.getTransaction();
        transaction.begin();
        /**
         *  merge:放到方法中的對象不會變成持久化對象,但是它會返回一個持久化對象,修改持久化對象同樣生效
         */
        //entityManager.persist(employee);
        Employee employee1 = entityManager.merge(employee);
        employee1.setName("更新創建者001");
        transaction.commit();
        JPAUtil.close(entityManager);
    }

執行上述操作同樣會發送兩條SQL語句:

 

 

3.4.Remove的使用

JPA中remove是不是直接刪除數據,而是修改一個對象的狀態為刪除狀態,當事務提交commit之後,delelte SQL語句才會發送,對應去刪除數據中的臟數據。

@Test
public void JPARemove() {
      EntityManager entityManager = JPAUtil.getEntityManager();
      EntityTransaction transaction = entityManager.getTransaction();
      transaction.begin();
      /**
       * remove並不是直接刪除數據,而是修改一個持久化對象的狀態為刪除狀態(計劃刪除)
       * 對應只能有一個entityManager,其它entityManager對象的持久化狀態在這裡是不能使用的
       */
      Employee employee = entityManager.find(Employee.class, 7);
      entityManager.remove(employee);
      transaction.commit();
      JPAUtil.close(entityManager);
}

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 背景 在做Electron Windows 桌面應用時候,做滑鼠懸浮到托盤圖標上時顯示一個懸浮框(例如做消息提醒),但因為Windows沒有提供托盤mouse-enter/mouse-leave事件,無法直接做這個功能,考慮到還有mouse-move事件,弄個間接的方式實現。 實現步驟 1、監聽mo ...
  • 今天看著視頻學習的時候遇到了,覺得以後會遇到,就記錄下來了 需求:點擊圖片,顯示遮擋層,同時下滑顯示視頻。點擊"X",遮擋層消失,同時視頻上滑隱藏。 具體代碼: 通過v-show控制整個video-box盒子的顯示與隱藏,可以提升性能。 <div class="item-video"> <h2> 6 ...
  • JavaScript實現無縫輪播圖: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0 ...
  • flex 佈局: 水平主軸:水平主軸開始位置到結束位置 垂直交叉軸:垂直交叉軸開始位置到結束位置 flex佈局屬性: flex佈局屬性: 屬性名稱 屬性值 解釋 備註 flex-direction(伸縮流方向) row 按行排列 從左到右 row-reverse 按行反向排列 從右到左 column ...
  • 六大設計原則 單一職責 定義 每個類都應該有一個單一的功能 一個類或者模塊應該有且只有一個改變的原因 規範 定義類的方法 避免類之間耦合度太高 里氏替換 定義 只要有父類出現的地方,都可以用子類來替代 規範 不要破壞繼承體系 增加子類的時候系統可以正常執行 依賴倒置原則 定義 高層模塊不應該依賴底層 ...
  • OO第二階段(5-8周)PTA作業總結 0.前言 本次博客針對的是PTA第二階段的作業,這次作業相比於第一階段來講難度、思維高度都提高了很多,耗費的精力和時間也很多但是收穫很大;這次作業很大一部分難點及側重點是在正則表達式上,這一部分確實難學,你要對程式的需求分析精準,不斷修改正則才能達到預期結果; ...
  • 前言 併發編程是java中不可或缺的模塊。與串列程式相比,它們能使複雜的非同步代碼變得簡單,從而極大地簡化了複雜系統的開發。此外,想要充分發揮多處理器系統的強大計算能力,最簡單的方式就是使用線程。隨著處理器數量的持續增長,如何高效地使用蝙蝠正變得越來越重要。同時在當今互聯網的時代,大量的互聯網應用都面 ...
  • 使用自定義視圖解析器: 配置自定義視圖跳轉: 通過配置擴展 SpringMVC: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...