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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

JavaWeb:JDBC之事务

發布時間:2025/4/16 java 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaWeb:JDBC之事务 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

系列閱讀

  • JavaWeb:用JDBC操作數據庫
  • JavaWeb:JDBC之事務
  • JavaWeb:JDBC之數據庫連接池
  • 使用JDBC實現水果超市管理系統
  • 1. 事務

    • 事務的四大特性:ACID
    • mysql中操作事務
    • jdbc中操作事務

    1.1 事務概述

    為了方便演示事務,我們需要創建一個account表:

    CREATE TABLE account(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(30),balance NUMERIC(10.2) );INSERT INTO account(NAME,balance) VALUES('zs', 100000); INSERT INTO account(NAME,balance) VALUES('ls', 100000); INSERT INTO account(NAME,balance) VALUES('ww', 100000);SELECT * FROM account;

    1.2 什么是事務

    銀行轉賬!張三轉10000塊到李四的賬戶,這其實需要兩條SQL語句:

    • 給張三的賬戶減去10000元
    • 給李四的賬戶加上10000元

    如果在第一條SQL語句執行成功后,在執行第二條SQL語句之前,程序被中斷了(可能是拋出了某個異常,也可能是其他什么原因),那么李四的賬戶沒有加上10000元,而張三卻減去了10000元。這肯定是不行的!

    你現在可能已經知道什么是事務了吧!事務中的多個操作,要么完全成功,要么完全失敗!不可能存在成功一半的情況!也就是說給張三的賬戶減去10000元如果成功了,那么給李四的賬戶加上10000元的操作也必須是成功的;否則給張三減去10000元,以及給李四加上10000元都是失敗的!

    1.3 事務的四大特性(ACID)

    事務的四大特性是:

    • 原子性(Atomicity):事務中所有操作是不可再分割的原子單位。事務中所有操作要么全部執行成功,要么全部執行失敗

    • 一致性(Consistency):事務執行后,數據庫狀態與其它業務規則保持一致。如轉賬業務,無論事務執行成功與否,參與轉賬的兩個賬號余額之和應該是不變的

    • 隔離性(Isolation):隔離性是指在并發操作中,不同事務之間應該隔離開來,使每個并發中的事務不會相互干擾

    • 持久性(Durability):一旦事務提交成功,事務中所有的數據操作都必須被持久化到數據庫中,即使提交事務后,數據庫馬上崩潰,在數據庫重啟時,也必須能保證通過某種機制恢復數據

    1.4 MySQL中的事務

    在默認情況下,MySQL每執行一條SQL語句,都是一個單獨的事務。如果需要在一個事務中包含多條SQL語句,那么需要開啟事務和結束事務。

    • 開啟事務:start transaction
    • 結束事務:commit或rollback

    在執行SQL語句之前,先執行strat transaction,這就開啟了一個事務(事務的起點),然后可以去執行多條SQL語句,最后要結束事務,commit表示提交,即事務中的多條SQL語句所做出的影響會持久化到數據庫中。或者rollback,表示回滾,即回滾到事務的起點,之前做的所有操作都被撤消了!

    下面演示zs給li轉賬10000元的示例:

    START TRANSACTION; UPDATE account SET balance=balance-10000 WHERE id=1; UPDATE account SET balance=balance+10000 WHERE id=2; ROLLBACK;START TRANSACTION; UPDATE account SET balance=balance-10000 WHERE id=1; UPDATE account SET balance=balance+10000 WHERE id=2; COMMIT;START TRANSACTION; UPDATE account SET balance=balance-10000 WHERE id=1; UPDATE account SET balance=balance+10000 WHERE id=2; quit;

    2. JDBC事務

    在jdbc中處理事務,都是通過Connection完成的!同一事務中所有的操作,都在使用同一個Connection對象!

    2.1、JDBC中的事務

    Connection的三個方法與事務相關:

    • setAutoCommit(boolean):設置是否為自動提交事務,如果true(默認值就是true)表示自動提交,也就是每條執行的SQL語句都是一個單獨的事務,如果設置false,那么就相當于開啟了事務了
    • commit():提交結束事務
    • rollback():回滾結束事務

    jdbc處理事務的代碼格式:

    try {con.setAutoCommit(false);//開啟事務…….…con.commit();//try的最后提交事務 } catch() {con.rollback();//回滾事務 }public void transfer(boolean b) {Connection con = null;PreparedStatement pstmt = null;try {con = JdbcUtils.getConnection();//手動提交con.setAutoCommit(false);String sql = "update account set balance=balance+? where id=?";pstmt = con.prepareStatement(sql);//操作pstmt.setDouble(1, -10000);pstmt.setInt(2, 1);pstmt.executeUpdate();// 在兩個操作中拋出異常if(b) {throw new Exception();}pstmt.setDouble(1, 10000);pstmt.setInt(2, 2);pstmt.executeUpdate();//提交事務con.commit();} catch(Exception e) {//回滾事務if(con != null) {try {con.rollback();} catch(SQLException ex) {}}throw new RuntimeException(e);} finally {//關閉JdbcUtils.close(con, pstmt);}}

    3. 保存點

    保存點是JDBC3.0的東西!當要求數據庫服務器支持保存點方式的回滾。
    校驗數據庫服務器是否支持保存點!

    boolean b = con.getMetaData().supportsSavepoints();

    保存點的作用是允許事務回滾到指定的保存點位置。在事務中設置好保存點,然后回滾時可以選擇回滾到指定的保存點,而不是回滾整個事務!注意,回滾到指定保存點并沒有結束事務!!!只有回滾了整個事務才算是結束事務了!

    Connection類的設置保存點,以及回滾到指定保存點方法:

    • 設置保存點:Savepoint setSavepoint()
    • 回滾到指定保存點:void rollback(Savepoint)
    /** 李四對張三說,如果你給我轉1W,我就給你轉100W。* ==========================================* * 張三給李四轉1W(張三減去1W,李四加上1W)* 設置保存點!* 李四給張三轉100W(李四減去100W,張三加上100W)* 查看李四余額為負數,那么回滾到保存點。* 提交事務*/@Testpublic void fun() {Connection con = null;PreparedStatement pstmt = null;try {con = JdbcUtils.getConnection();//手動提交con.setAutoCommit(false);String sql = "update account set balance=balance+? where name=?";pstmt = con.prepareStatement(sql);//操作1(張三減去1W)pstmt.setDouble(1, -10000);pstmt.setString(2, "zs");pstmt.executeUpdate();//操作2(李四加上1W)pstmt.setDouble(1, 10000);pstmt.setString(2, "ls");pstmt.executeUpdate();// 設置保存點Savepoint sp = con.setSavepoint();//操作3(李四減去100W)pstmt.setDouble(1, -1000000);pstmt.setString(2, "ls");pstmt.executeUpdate(); //操作4(張三加上100W)pstmt.setDouble(1, 1000000);pstmt.setString(2, "zs");pstmt.executeUpdate();//操作5(查看李四余額)sql = "select balance from account where name=?";pstmt = con.prepareStatement(sql);pstmt.setString(1, "ls");ResultSet rs = pstmt.executeQuery();rs.next();double balance = rs.getDouble(1);//如果李四余額為負數,那么回滾到指定保存點if(balance < 0) {con.rollback(sp);System.out.println("張三,你上當了!");}//提交事務con.commit();} catch(Exception e) {//回滾事務if(con != null) {try {con.rollback();} catch(SQLException ex) {}}throw new RuntimeException(e);} finally {//關閉JdbcUtils.close(con, pstmt);}}

    4. 事務隔離級別

    4.1 事務的并發讀問題

    • 臟讀:讀取到另一個事務未提交數據
    • 不可重復讀:兩次讀取不一致
    • 幻讀(虛讀):讀到另一事務已提交數據

    4.2 并發事務問題

    因為并發事務導致的問題大致有5類,其中兩類是更新問題,三類是讀問題

    • 臟讀(dirty read):讀到另一個事務的未提交更新數據,即讀取到了臟數據
    • 不可重復讀(unrepeatable read):對同一記錄的兩次讀取不一致,因為另一事務對該記錄做了修改
    • 幻讀(虛讀)(phantom read):對同一張表的兩次查詢不一致,因為另一事務插入了一條記錄

    4.2.1 臟讀

    事務1:張三給李四轉賬100元
    事務2:李四查看自己的賬戶

    • t1:事務1:開始事務
    • t2:事務1:張三給李四轉賬100元
    • t3:事務2:開始事務
    • t4:事務2:李四查看自己的賬戶,看到賬戶多出100元(臟讀)
    • t5:事務2:提交事務
    • t6:事務1:回滾事務,回到轉賬之前的狀態

    4.2.2不可重復讀

    事務1:酒店查看兩次1048號房間狀態
    事務2:預訂1048號房間

    • t1:事務1:開始事務
    • t2:事務1:查看1048號房間狀態為空閑
    • t3:事務2:開始事務
    • t4:事務2:預定1048號房間
    • t5:事務2:提交事務
    • t6:事務1:再次查看1048號房間狀態為使用
    • t7:事務1:提交事務
      對同一記錄的兩次查詢結果不一致!

    4.2.3幻讀

    事務1:對酒店房間預訂記錄兩次統計
    事務2:添加一條預訂房間記錄

    • t1:事務1:開始事務
    • t2:事務1:統計預訂記錄100條
    • t3:事務2:開始事務
    • t4:事務2:添加一條預訂房間記錄
    • t5:事務2:提交事務
    • t6:事務1:再次統計預訂記錄為101記錄
    • t7:事務1:提交

    對同一表的兩次查詢不一致!

    不可重復讀和幻讀的區別:

    • 不可重復讀是讀取到了另一事務的更新;
    • 幻讀是讀取到了另一事務的插入(MySQL中無法測試到幻讀);

    4.3 四大隔離級別

    4個等級的事務隔離級別,在相同數據環境下,使用相同的輸入,執行相同的工作,根據不同的隔離級別,可以導致不同的結果。不同事務隔離級別能夠解決的數據并發問題的能力是不同的

    4.3.1 SERIALIZABLE(串行化)

    • 不會出現任何并發問題,因為它是對同一數據的訪問是串行的,非并發訪問的
    • 性能最差

    4.3.2 REPEATABLE READ(可重復讀)(MySQL)

    • 防止臟讀和不可重復讀,不能處理幻讀問題
    • 性能比SERIALIZABLE好

    4.3.3 READ COMMITTED(讀已提交數據)(Oracle)

    • 防止臟讀,沒有處理不可重復讀,也沒有處理幻讀;
    • 性能比REPEATABLE READ好

    4.3.4 READ UNCOMMITTED(讀未提交數據)

    • 可能出現任何事務并發問題
    • 性能最好

    MySQL的默認隔離級別為REPEATABLE READ,這是一個很不錯的選擇吧!

    4.3.5 MySQL隔離級別

    MySQL的默認隔離級別為Repeatable read,可以通過下面語句查看:

    select @@tx_isolation

    也可以通過下面語句來設置當前連接的隔離級別:

    set transaction isolationlevel [41]

    4.3.6 JDBC設置隔離級別

    con. setTransactionIsolation(int level);參數可選值如下:

    • Connection.TRANSACTION_READ_UNCOMMITTED
    • Connection.TRANSACTION_READ_COMMITTED
    • Connection.TRANSACTION_REPEATABLE_READ
    • Connection.TRANSACTION_SERIALIZABLE

    5. 事務總結

    • 事務的特性:ACID
    • 事務開始邊界與結束邊界:開始邊界(con.setAutoCommit(false)),結束邊界(con.commit()或con.rollback())
    • 事務的隔離級別: READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE。多個事務并發執行時才需要考慮并發事務

    總結

    以上是生活随笔為你收集整理的JavaWeb:JDBC之事务的全部內容,希望文章能夠幫你解決所遇到的問題。

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