1. 程式人生 > >javaweb學習總結(三十八)——事務

javaweb學習總結(三十八)——事務

一、事務的概念

  事務指邏輯上的一組操作,組成這組操作的各個單元,要不全部成功,要不全部不成功
  例如:A——B轉帳,對應於如下兩條sql語句
    update from account set money=money+100 where name='B';
    update from account set money=money-100 where name='A';

二、MySQL資料庫中操作事務命令

  1、編寫測試SQL指令碼,如下:

 1 /*建立賬戶表*/
 2 create table account(
 3     id int primary key auto_increment,
4 name varchar(40), 5 money float 6 ); 7 8 /*插入測試資料*/ 9 insert into account(name,money) values('A',1000); 10 insert into account(name,money) values('B',1000); 11 insert into account(name,money) values('C',1000);

  下面我們在MySQL資料庫中模擬A——B轉帳這個業務場景

2.1、開啟事務(start transaction)

  使用"start transaction"開啟MySQL資料庫的事務,如下所示:

  

  我們首先在資料庫中模擬轉賬失敗的場景,首先執行update語句讓A使用者的money減少100塊錢,如下圖所示:

  

  然後我們關閉當前操作的dos命令列視窗,這樣就導致了剛才執行的update語句的資料庫的事務沒有被提交,那麼我們對A使用者的修改就不算是是真正的修改了,下次在查詢A使用者的money時,依然還是之前的1000,如下圖所示:

  

2.2、提交事務(commit)

  下面我們在資料庫模擬A——B轉賬成功的場景

  

  我們手動提交(commit)資料庫事務之後,A——B轉賬100塊錢的這個業務操作算是真正成功了,A賬戶中少了100,B賬戶中多了100。

2.3、回滾事務(rollback)

  

  通過手動回滾事務,讓所有的操作都失效,這樣資料就會回到最初的初始狀態!

三、JDBC中使用事務

  當Jdbc程式向資料庫獲得一個Connection物件時,預設情況下這個Connection物件會自動向資料庫提交在它上面傳送的SQL語句。若想關閉這種預設提交方式,讓多條SQL在一個事務中執行,可使用下列的JDBC控制事務語句

  • Connection.setAutoCommit(false);//開啟事務(start transaction)
  • Connection.rollback();//回滾事務(rollback)
  • Connection.commit();//提交事務(commit)

3.1、JDBC使用事務範例

  在JDBC程式碼中演示銀行轉帳案例,使如下轉帳操作在同一事務中執行

  "update account set money=money-100 where name='A'"

  update account set money=money+100 where name='B'

  程式碼如下:

  1 package me.gacl.demo;
  2 
  3 import java.sql.Connection;
  4 import java.sql.PreparedStatement;
  5 import java.sql.ResultSet;
  6 import java.sql.SQLException;
  7 import me.gacl.utils.JdbcUtils;
  8 import org.junit.Test;
  9 
 10 /**
 11 * @ClassName: TransactionDemo1
 12 * @Description: 
 13 * JDBC中使用事務來模似轉帳 
 14     create table account(
 15         id int primary key auto_increment,
 16         name varchar(40),
 17         money float
 18     );
 19     insert into account(name,money) values('A',1000);
 20     insert into account(name,money) values('B',1000);
 21     insert into account(name,money) values('C',1000);
 22 * @author: 孤傲蒼狼
 23 * @date: 2014-9-22 下午11:16:17
 24 *
 25 */ 
 26 public class TransactionDemo1 {
 27 
 28     /**
 29     * @Method: testTransaction1
 30     * @Description: 模擬轉賬成功時的業務場景
 31     * @Anthor:孤傲蒼狼
 32     *
 33     */ 
 34     @Test
 35     public void testTransaction1(){
 36         Connection conn = null;
 37         PreparedStatement st = null;
 38         ResultSet rs = null;
 39         
 40         try{
 41             conn = JdbcUtils.getConnection();
 42             conn.setAutoCommit(false);//通知資料庫開啟事務(start transaction)
 43             String sql1 = "update account set money=money-100 where name='A'";
 44             st = conn.prepareStatement(sql1);
 45             st.executeUpdate();
 46             String sql2 = "update account set money=money+100 where name='B'";
 47             st = conn.prepareStatement(sql2);
 48             st.executeUpdate();
 49             conn.commit();//上面的兩條SQL執行Update語句成功之後就通知資料庫提交事務(commit)
 50             System.out.println("成功!!!");  //log4j
 51         }catch (Exception e) {
 52             e.printStackTrace();
 53         }finally{
 54             JdbcUtils.release(conn, st, rs);
 55         }
 56     }
 57     
 58     /**
 59     * @Method: testTransaction1
 60     * @Description: 模擬轉賬過程中出現異常導致有一部分SQL執行失敗後讓資料庫自動回滾事務
 61     * @Anthor:孤傲蒼狼
 62     *
 63     */ 
 64     @Test
 65     public void testTransaction2(){
 66         Connection conn = null;
 67         PreparedStatement st = null;
 68         ResultSet rs = null;
 69         
 70         try{
 71             conn = JdbcUtils.getConnection();
 72             conn.setAutoCommit(false);//通知資料庫開啟事務(start transaction)
 73             String sql1 = "update account set money=money-100 where name='A'";
 74             st = conn.prepareStatement(sql1);
 75             st.executeUpdate();
 76             //用這句程式碼模擬執行完SQL1之後程式出現了異常而導致後面的SQL無法正常執行,事務也無法正常提交,此時資料庫會自動執行回滾操作
 77             int x = 1/0;
 78             String sql2 = "update account set money=money+100 where name='B'";
 79             st = conn.prepareStatement(sql2);
 80             st.executeUpdate();
 81             conn.commit();//上面的兩條SQL執行Update語句成功之後就通知資料庫提交事務(commit)
 82             System.out.println("成功!!!");
 83         }catch (Exception e) {
 84             e.printStackTrace();
 85         }finally{
 86             JdbcUtils.release(conn, st, rs);
 87         }
 88     }
 89     
 90     /**
 91     * @Method: testTransaction1
 92     * @Description: 模擬轉賬過程中出現異常導致有一部分SQL執行失敗時手動通知資料庫回滾事務
 93     * @Anthor:孤傲蒼狼
 94     *
 95     */ 
 96     @Test
 97     public void testTransaction3(){
 98         Connection conn = null;
 99         PreparedStatement st = null;
100         ResultSet rs = null;
101         
102         try{
103             conn = JdbcUtils.getConnection();
104             conn.setAutoCommit(false);//通知資料庫開啟事務(start transaction)
105             String sql1 = "update account set money=money-100 where name='A'";
106             st = conn.prepareStatement(sql1);
107             st.executeUpdate();
108             //用這句程式碼模擬執行完SQL1之後程式出現了異常而導致後面的SQL無法正常執行,事務也無法正常提交
109             int x = 1/0;
110             String sql2 = "update account set money=money+100 where name='B'";
111             st = conn.prepareStatement(sql2);
112             st.executeUpdate();
113             conn.commit();//上面的兩條SQL執行Update語句成功之後就通知資料庫提交事務(commit)
114             System.out.println("成功!!!");
115         }catch (Exception e) {
116             try {
117                 //捕獲到異常之後手動通知資料庫執行回滾事務的操作
118                 conn.rollback();
119             } catch (SQLException e1) {
120                 e1.printStackTrace();
121             }
122             e.printStackTrace();
123         }finally{
124             JdbcUtils.release(conn, st, rs);
125         }
126     }
127 }

 3.2、設定事務回滾點

  在開發中,有時候可能需要手動設定事務的回滾點,在JDBC中使用如下的語句設定事務回滾點

  Savepoint sp = conn.setSavepoint();
  Conn.rollback(sp);
  Conn.commit();//回滾後必須通知資料庫提交事務
  設定事務回滾點範例

 1 package me.gacl.demo;
 2 
 3 import java.sql.Connection;
 4