Hibernate | Spring JPA | MySQL 使用過程遇到的一些問題

来源:https://www.cnblogs.com/lger/archive/2018/04/21/8895525.html
-Advertisement-
Play Games

"1. 使用過程" "2. 背景" "3. 遇到問題" "3.1 不指定Hibernate資料庫方言,預設SQL生成方式" "3.2 拋出異常Hibernate加入了@Transactional事務不會回滾" "3.3 Hibernate使用Spring Test測試加入了@Transactiona ...


1. 使用過程

  在項目中我使用Spring Boot 2.0.0.RELEASE開發並且集成了Spring JPA;我這裡將Hibernate版本設置為5.1.2.Final,這裡做修改主要是因為LocalDate跟資料庫映射時有些問題才做更換,其他基本沒什麼大的問題;資料庫使用了MySQL
  

2. 背景

  使用MySQL,所以先對MySQL做一些瞭解,這裡MySQL資料庫中有四種存儲引擎,主要介紹兩種,分別為MyISAMInnoDB,它們兩個的區別如下:

InnoDB MyISAM
訪問速度 相對慢
事務 支持 不支持
外鍵 支持 不支持
應用場景 需要事務提交、回滾功能應用 以查詢為主的應用

各種引擎簡要介紹
https://blog.csdn.net/qq_27028821/article/details/52267991

3. 遇到問題

3.1 不指定Hibernate資料庫方言,預設SQL生成方式

在不指定方言的情況下預設使用了MySQL5Dialect,這樣在列印create table命令時會在後面指定它的資料庫引擎為MyISAM,這樣生成的資料庫是不支持外鍵的,也是不支持事務性操作的。請註意是資料庫。

3.2 拋出異常Hibernate加入了@Transactional事務不會回滾

現在這裡有個實體類:

@Entity
@Data
public class Test{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    
    private String name;
    
}

我們保存需要保存一個Test實例時發現拋出了一個異常資料庫居然保存成功,代碼如下:

Service:

    @Resource
    private TestDao testDao;

    @Transactional
    public void test(){
        Test test = new Test();
        test.setName("test");
        testDao.save(test);
        int a = 1 / 0;
    }

這裡我們要看回去MySQL生成的方式,預設是使用了MyISAM這是不支持事務的,如果向資料庫保存了數據,那麼事務回滾也是不管用的,所以,現在我們需要指定配置資料庫的方言,在Spring Boot中可在application.properties配置如下:

spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect

如果是xml配置的可以這麼配置

<property name="dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>

這樣我們重新運行生成的表可以有外鍵生成也可以支持資料庫事務,當然數據就可以回滾了
當然了,除了以上的解決方法之外,其實還有一個不怎麼好的解決方法,那就是將Test中的id生成策略註解改為如下內容:

@Entity
@Data
public class Test{
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    
    private String name;
    
}

對於這個為什麼可以,請接著往下麵看

主鍵生成策略參考
https://blog.csdn.net/lwt976647637/article/details/53352369

3.3 Hibernate使用Spring Test測試加入了@Transactional事務無論如何資料庫插入不成功

  這裡使用上面修改成AUTO的實體類

  在測試類裡面我們可以保存我們一個Test對象,測試代碼如下:

junit.Test

    @Test
    @Transactional
    public void test(){
        Test test = new Test();
        test.setName("test");
        testDao.save(test);
    }

上面沒有任何異常拋出,進度條也綠了,但是數據插入資料庫不成功,這時,可以看下控制台列印輸出的語句:

//....前面有很多,不寫出來了
transaction manager [org.springframework.orm.jpa.JpaTransactionManager@5e5ddfbc]; rollback [true]

這裡我大膽的猜測就是Spring Test自動幫我們把事務回滾了,我們如果要看到把數據插入資料庫的話只是需要在test方法加入註解,如

    @Test
    @Transactional
    @Rollback(false) //設置事務不自動回滾
    public void test(){
        Test test = new Test();
        test.setName("test");
        testDao.save(test);
    }

3.4 Hibernate在使用MyISAM引擎也可以回滾?

  我在之前寫的會員管理系統中是沒有指定生成方言的,預設是使用了MyISAM,但是在Service中出現了異常還是可以回滾,怎麼回事?
  這是因為我們在save之後Hibernate不會立馬執行SQL的,除非是事務提交了,我在事務提交之前拋出了異常,所以在Hibernate的緩存中的SQL是不會執行成功的,因此就用假的回滾現象,這不是資料庫提供的回滾功能。
  

3.5 Hibernate在使用生成策略是IDENTITY不能回滾事務,AUTO可以

  
  這是因為如果使用了IDENTITY是資料庫維護我們的主鍵,Hibernate為了獲取id是需要向資料庫插入數據才能獲得id的值的,所以會執行SQL,在使用MyISAM引擎的情況下是不能回滾事務的
  如果用了AUTO那麼不需要資料庫維護,Hibernate自己維護是不需要向資料庫要主鍵的,那麼不會立馬執行SQL就跟上一個問題一樣的結果。所以這裡的生成策略使用uuid也是可以的,只要不是資料庫維護。
  
  

3.6 使用MyISAM引擎下有緩存的情況@Controller下使用事務回滾不成功,@Service下成功

  在Controller層使用@Transactional事務是不會回滾的,但是Service層就可以,如果把@Controller替換成@Component也是成功的。
  我做了下調試,發現Controller調用方法如下圖:
  
Service調用事務方法如下圖:
  
也就是代理方式不同,一種是JDK代理一種是CGLib代理,有可能是這個導致了AOP實現的事務是調用不成功的,具體可以自行搜索AOP與動態代理相關的知識(原諒我知識局限)。

4. 總結

   這裡遇到大部分問題終其原因都是MySQL引擎使用或是沒有指定方言的原因吧,所以,沒有性能方面的要求或者是小白請使用InnoDB引擎。
   而對於我來說,這些異常手動catch算是學到了些東西,但是會遇到問題說明自己還是沒有瞭解它,不說了,好好學習。


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

-Advertisement-
Play Games
更多相關文章
  • react 的 antd框架中 form使用需註意: 1、不能用state改變下拉框、輸入框等組件的值,因為 經過 getFieldDecorator 包裝的控制項,表單控制項會自動添加 value(或 valuePropName 指定的其他屬性) onChange(或 trigger 指定的其他屬性) ...
  • 參考書《ECMAScript 6入門》http://es6.ruanyifeng.com/Reflect1.概述:Object對象的內部方法都能在Reflect中找到,同時Reflect將Object的一些命令改成了函數操作,且Reflect與Proxy一一對應。2.靜態方法Object,Refle ...
  • 邏輯理解:當程式執行setTimeout()和setInterval()時,會讓這兩者到後臺(我的理解,事實是否如此,有待驗證)運行計時,當時間到了之後,將回調函數按照順序依次排在當前正在執行的函數隊列尾部。哪怕延遲為0也一樣,當前正在執行解析的Javascript解析器並不會立即執行定時器的回調函 ...
  • 最近在學react,然後感覺自己之前用的express+gulp+webpack+ejs的工作環境還是基於html+js+css這種三層架構的應用,完全跟react不是一回事。 愚蠢的我居然在原先的這個環境上又搭建了react的環境。好吧,寫是能寫,但是作為服務端的架構就顯得驢唇不對馬嘴。不免對環境 ...
  • 由於業務需要,要求實現樹形菜單,且菜單數據由後臺返回,在網上找了幾篇文章,看下來總算有瞭解決辦法。借鑒文章鏈接在最底部。 場景:根據業務要求,需要實現活動的樹形菜單,菜單數據由後臺返回,最後的效果圖如下: 後臺返回的數據格式是這個樣子的: data=[{ pID:'1',//父ID name:'目錄 ...
  • 一:字體代碼:作用--顏色 1、.text-muted:提示--淺灰色 2、.text-primary:主要--藍色 3、.text-success:成功--淺綠色 4、.text-info: 通知--淺藍色 5、.text-warning: 警告--黃色 6、.text-danger:危險--褐色 ...
  • 一.概念: 設計模式是人們在面對同類型軟體工程設計問題所總結出的一些有用經驗 模式不是代碼而是某類問題的通用設計解決方案 設計模式的本質目的是使軟體工程在維護性、擴展性、變化性、複雜度方面成O(N) 學習設計模式最好的方式是在你的設計和以往的工程里尋找何處可以使用它們 二.OO的六大原則: 1. S ...
  • Eureka Server 在運行期間會去統計心跳失敗比例在 15 分鐘之內是否低於 85%,如果低於 85%,Eureka Server 會將這些實例保護起來,讓這些實例不會過期,但是在保護期內如果服務剛好這個服務提供者非正常下線了,此時服務消費者就會拿到一個無效的服務實例,此時會調用失敗,對於這 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...