Mybatis--事務控制

韓家小志發表於2020-12-14

1 JDBC中事務的回顧

一:什麼是事務?

在這裡插入圖片描述

二:事務的四大特性ACID?

在這裡插入圖片描述

三:不考慮隔離性會產生的3個問題?

  • 髒讀
    • (針對未提交資料)如果一個事務中對資料進行了更新,但事務還沒有提交,另一個事務可以“看到”該事務沒有提交的更新結果,這樣造成的問題就是,如果第一個事務回滾,那麼,第二個事務在此之前所“看到”的資料就是一筆髒資料。
  • 不可重複讀
    • (針對其他提交前後,讀取資料本身的對比)不可重複讀取是指同一個事務在整個事務過程中對同一筆資料進行讀取,每次讀取結果都不同。如果事務1在事務2的更新操作之前讀取一次資料,在事務2的更新操作之後再讀取同一筆資料一次,兩次結果是不同的
  • 幻讀
    • (針對其他提交前後,讀取資料條數的對比) 幻讀是指同樣一筆查詢在整個事務過程中多次執行後,查詢所得的結果集是不一樣的。幻讀針對的是多筆記錄。如果事務1在事務2的新增操作之前讀取一次資料,在事務2的新增操作之後再讀取同一筆資料,取得的結果集是不同的,幻讀發生。
      不可重複讀和幻讀比較:
      兩者有些相似,但是前者針對的是update或delete,後者針對的insert。

四:解決辦法:四種隔離級別?

  • 1、Serializable (序列化):最嚴格的級別,事務序列執行,資源消耗最大;
  • 2、REPEATABLE READ(重複讀) :保證了一個事務不會修改已經由另一個事務讀取但未提交(回滾)的資料。避免了“髒讀”和“不可重複讀”的情況,但不能避免“幻讀”,但是帶來了更多的效能損失。(mysql的預設隔離級別)
  • 3、READ COMMITTED (讀已提交):大多數主流資料庫的預設事務等級,保證了一個事務不會讀到另一個並行事務已修改但未提交的資料,避免了“髒讀”,但不能避免“幻讀”和“不可重複讀”。該級別適用於大多數系統。(oracle的預設隔離級別)
  • 4、Read Uncommitted(讀未提交) :事務中的修改,即使沒有提交,其他事務也可以看得到,會導致“髒讀”、“幻讀”和“不可重複讀取”。
try{
    // 1 獲取連線,  開啟事務
    conn.setAutocommit(false)
    // 2 執行一組sql語句
    // 2.1 出錢
    // 2.2 收款
    // 3.1 沒有問題 提交事務
    conn.commit();
} catch(){
    // 3.2 出現問題 回滾事務
    conn.rollback()
} fianlly {
    // 4 釋放資源
    .. ...
}

五:事務的提交和回滾。

  • 通過sqlsession物件的commit方法和rollback方法實現事務的提交和回滾
  • 在JDBC中我們可以通過手動方式將事務的提交改為手動方式,通過setAutoCommit()方法就可以調整。
  • 通過JDK文件,我們找到該方法如下:在這裡插入圖片描述
  • 那麼我們的Mybatis框架因為是對JDBC的封裝,所以Mybatis框架的事務控制方式,本身也是用JDBC的setAutoCommit()方法來設定事務提交方式的。
  • 底層:JdbcTransaction.java在這裡插入圖片描述

2 Mybatis中事務提交方式

  • Mybatis中事務的提交方式,本質上就是呼叫JDBC的setAutoCommit()來實現事務控制。
  • 我們執行之前所寫的程式碼:
    在這裡插入圖片描述
  • 檢視DefaultSqlSessionFactory的openSession();方法
  • 設定為false表示需要手動提交事務。
    • 這是我們的Connection的整個變化過程,通過分析我們能夠發現之前的CUD操作過程中,我們都要手動進行事務的提交,原因是setAutoCommit()方法,在執行時它的值被設定為false了,所以我們在CUD操作中,必須通過sqlSession.commit()方法來執行提交操作。在這裡插入圖片描述
  • 檢視SqlSession.commit();方法
  • 還是呼叫了JdbcTransaction.java
    在這裡插入圖片描述
  • 測試自動提交:
    在這裡插入圖片描述
  • 總結:如果設定此時事務就設定為自動提交了,同樣可以實現CUD操作時記錄的儲存。雖然這也是一種方式,但就程式設計而言,設定為自動提交方式為false再根據情況決定是否進行提交,這種方式更常用。因為我們可以根據業務情況來決定業務是否進行提交。如果設定自動提交,如果當前操作有誤,事務很難設定回滾了。 只有設定為手動提交,我們才能更好的控制事務。
try{
   // 操作業務1
   // 操作業務2
   session.commit();
}
catch(Exeception ex){
   session.rollback();
}

相關文章