MySql事務及JDBC對事務的使用


 一 、事務的幾個重要特性

1. 原子性

  事務內的每個內容不可分割,是一個統一的整體。或同時進行或同時消亡。

2.一致性

      事務執行前和事務執行后,狀態都是統一的。如A轉B 100元,A和B數據總額度沒有在這個轉賬過程中增加或者減小。

3.隔離性【isolation】

  事務的隔離性指的是幾個事務同時執行,事務a不應該干擾到事務b內的操作(在並發過程中很有可能會發生事務間的影響,例如臟讀、不可重復讀等。需要在編程的時候選擇適當的方式進行選擇)

3.可持久性

  事務執行后的結果可以存儲(序列化)到硬盤上,形成一個固定的內容存儲起來。

 

 二、事務的使用

  事務的生命周期有2個,1開啟事務 2提交或者回滾事務。事務開始后一定要提交或者回滾,以免引起數據庫內存泄漏

  使用Mysql開啟事務及使用。

  表內數據如下,現需要從a賬號轉100money到b賬號。

 

具體步驟如下:

   Mysql 中與事務使用有關的三個關鍵語句:

      (1) 開啟事務 : start transaction

      (2)回滾事務 :rollback , 提交事務:commit

 三、使用JDBC對事務進行調用

 △注意: 事務只能對DML語句進行操作,對數據定義類語句DDL無法操作,例如建表、建立索引、建立分區等。

 JDBC使用事務時,需要使用Java語言中的Connection對事務進行操作,具體的事務對應一個數據庫連接。

 1 package com.scl.test.transcaction;
 2 
 3 import java.sql.Connection;
 4 import java.sql.Statement;
 5 
 6 import org.junit.Test;
 7 
 8 public class TestTranscaction
 9 {
10 
11     @Test
12     public void testTransaction() throws Exception
13     {
14         Connection conn = null;
15         Statement statement = null;
16 
17         try
18         {
19             conn = JDBCHelper.getConnection();
20 
21             conn.setAutoCommit(false); //開啟事務,禁止自動提交
22             String sql1 = "update t_account t set t.money=t.money-100 where t.name ='a'";
23             String sql2 = "update t_account t set t.money=t.money+100 where t.name ='b'";
24             statement = conn.createStatement();
25             // statement.setString(1, "a");
26 
27             statement.addBatch(sql1);
28             statement.addBatch(sql2);
29 
30 
31             statement.executeBatch();
32             conn.commit(); //執行成功,提交事務
33 
34         }
35         catch (Exception e)
36         {
37             conn.rollback(); //發生異常,事務回滾
38         }
39         finally
40         {
41             JDBCHelper.disposeConnect(statement, conn);
42         }
43     }
44 }
View Code

 

  最后進行一個知識點補漏:JDBC執行多條sql腳本。

  JDBC提供了執行多條sql語句的方法,使用PrepareStatement或Statement實例調用addBatch方法。目前發現該方法有幾個缺點:

  1. 無法通過PrepareStatement實例對多條不同的sql腳本進行參數化設置。因為PrepareStatement是由一個鏈接產生的,不能同時用一個prepareStatement實例同時對應兩個不同的預處理文件。

   如需求:需要插入更新一張表里面的兩行不同的數據。 

        sql1: update t_account t set t.money=t.money-100 where t.name ='a';

   sql2: update t_account t set t.money=t.money-100 where t.name ='b';

   這時候沒辦法使用prepareStatement的addBatch方法執行操作。見代碼:

 1     @Test
 2     public void testTransaction() throws Exception
 3     {
 4         Connection conn = null;
 5         Statement st = null;
 6         PreparedStatement pst = null;
 7         try
 8         {
 9             conn = JDBCHelper.getConnection();
10 
11             conn.setAutoCommit(false);
12             String sql1 = "update t_account t set t.money=t.money-100 where t.name =?";
13             String sql2 = "update t_account t set t.money=t.money+100 where t.name =?";
14             pst = conn.prepareStatement(sql1);
15             // 只能批量執行某一條固定的sql語句,並且進行參數化設置
16             pst.setString(1, "a"); // 為name 為 a的用戶減少100元
17             pst.addBatch();
18             pst.setString(1, "b"); // 為name 為b的用戶減少100元
19             pst.addBatch();
20             pst.executeBatch(); // 只能在執行完成以后提交一次,然后改成新的sql腳本。但容易引發內存泄漏
21 
22             pst = conn.prepareStatement(sql2); // 內存泄漏,存在未關閉的鏈接
23             pst.setString(1, "c");
24             pst.addBatch();
25             pst.executeBatch();
26             conn.commit();
27 
28         }
29         catch (Exception e)
30         {
31             conn.rollback();
32         }
33         finally
34         {
35             JDBCHelper.disposeConnect(pst, conn);
36         }
37     }
View Code

 

       2. 使用statement實例對多條腳本進行提交(只提交一次,但無法進行預編譯sql腳本)

 1     @Test
 2     public void testTransaction() throws Exception
 3     {
 4         Connection conn = null;
 5         Statement st = null;
 6         PreparedStatement pst = null;
 7         try
 8         {
 9             conn = JDBCHelper.getConnection();
10 
11             conn.setAutoCommit(false);
12             String sql1 = "update t_account t set t.money=t.money-100 where t.name =?";
13             String sql2 = "update t_account t set t.money=t.money+100 where t.name =?";
14             pst = conn.prepareStatement(sql1);
15             // 只能批量執行某一條固定的sql語句,並且進行參數化設置
16             pst.setString(1, "a"); // 為name 為 a的用戶減少100元
17             pst.addBatch();
18             pst.setString(1, "b"); // 為name 為b的用戶減少100元
19             pst.addBatch();
20             pst.executeBatch(); // 只能在執行完成以后提交一次,然后改成新的sql腳本。但容易引發內存泄漏
21 
22             pst = conn.prepareStatement(sql2); // 內存泄漏,存在未關閉的鏈接
23             pst.setString(1, "c");
24             pst.addBatch();
25             pst.executeBatch();
26             conn.commit();
27 
28         }
29         catch (Exception e)
30         {
31             conn.rollback();
32         }
33         finally
34         {
35             JDBCHelper.disposeConnect(pst, conn);
36         }
37     }
View Code

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM