Spring架構——批處理(batch)和事務(Transaction)

來源:互聯網
上載者:User

標籤:成功   銀行   util   for迴圈   原來   地址   catch   where   nsis   

批處理(batch)

批處理(batch)------------>好比快遞員【不能一件一件的送快遞】
- 批處理指的是一次操作中執行多條SQL語句
- 批處理相比於一次一次執行效率會提高很多

- 批處理主要是分兩步:
  1.將要執行的SQL語句儲存
  2.執行SQL語句

- Statement和PreparedStatement都支援批處理操作,這裡我們只需要掌握PreparedStatement的批處理方式:
- 方法:
  void addBatch()
- 將要執行的SQL先儲存起來,先不執行
- 這個方法在設定完所有的預留位置之後調用
  int[] executeBatch()
- 這個方法用來執行SQL語句,這個方法會將批處理中所有SQL語句執行

- mysql預設批處理是關閉的,所以我們還需要去開啟mysql的批處理:
  rewriteBatchedStatements=true
我們需要將以上的參數添加到mysql的url地址中

- 注意:低版本的mysql-jdbc驅動也不支援批處理,一般都是在修改的時候使用批處理,查詢的時候不使用!


案例示範:
1.建立一張新的資料表

CREATE TABLE t_emp(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(50))

  

2.反覆開啟資料庫用戶端,插入語句【相當於每次擷取一個connection串連,執行executeUpdate語句】

INSERT INTO t_emp(NAME) VALUES(‘張三‘);SELECT * FROM t_emp;


3.引出批處理--->執行效率高,資源使用率好!

@Test//測試批處理public void testBatch(){//向t_emp表中插入10000條資料  //準備兩個變數  Connection connection = null;  PreparedStatement ps = null;  try {    //擷取資料庫連接    connection=JDBCUtil.getConnection();    //準備SQL模板    String sql = "INSERT INTO t_emp(NAME) VALUES(?)";    //擷取PrepareStatement    ps = connection.prepareStatement(sql);    //建立一個for迴圈,來設定預留位置    for(int i = 0; i < 10000 ;i++){      //填充預留位置      ps.setString(1,"emp"+i);      //添加到批處理方法中,調用無參的,有參的是Statement來調用的!      ps.addBatch();    }     //擷取一個時間戳記    long start = System.currentTimeMillis();    //執行批處理    ps.executeBatch();    //擷取一個時間戳記    long end = System.currentTimeMillis();    System.out.println("共花費了:"+(end-start));  } catch (SQLException e) {    e.printStackTrace();  }}

  

事務(Transaction)

示範銀行轉賬的功能:
1.建立一張表示帳號的表

CREATE TABLE t_account(id INT PRIMARY KEY AUTO_INCREMENT,a_name VARCHAR(50),balance DECIMAL(11,2))

 


2.向表中插入幾個使用者

INSERT INTO t_account(id,a_name,balance) VALUES(NULL,‘sunwukong‘,1000);INSERT INTO t_account(id,a_name,balance) VALUES(NULL,‘zhubajie‘,1000);INSERT INTO t_account(id,a_name,balance) VALUES(NULL,‘shaheshang‘,1000);SELECT * FROM t_account;

 


3.sunwukong向shaheshang轉賬100元
從sunwukong的帳號減去100元

UPDATE t_account SET balance = balance - 100 WHERE a_name=‘sunwukong‘;

給shaheshang的帳號加上100元

UPDATE t_account SET balance = balance +100 WHERE a_name = ‘shaheshang‘;

 


重新設定為1000元:

UPDATE t_account SET balance =1000;

 


4.從java代碼中示範上面的案例:
1.建立Dao類

public class AcountDao {  public void update(String name,double money){    //準備兩個變數    Connection conn = null;    PreparedStatement ps = null;    //準備SQL模板    String sql = "UPDATE t_account SET balance = balance + ? WHERE a_name = ?";    try {      conn = JDBCUtil.getConnection();      //擷取PreparedStatement      ps = conn.prepareStatement(sql);      //填充預留位置      ps.setDouble(1, money);      ps.setString(2, name);      //執行SQL語句      ps.executeUpdate();    } catch (SQLException e) {      // TODO Auto-generated catch block      e.printStackTrace();    }finally{      JDBCUtil.close(conn, ps, null);    }  }}

  


2.測試該DAO

public class TestTransaction {  private AcountDao accountDao = new AcountDao();  @Test  public void test() {    //從sunwukong賬戶向shaheshang賬戶轉賬100元!    //1.從sunwukong賬戶扣除100元    accountDao.update("sunwukong", -100);    //2.向shaheshang賬戶添加100元    accountDao.update("shaheshang", 100);  }}

  


顯然上面是可以正常執行的!
但是如果上面的程式在suwukong減去100元之後,shaheshang加錢之前,出現了異常,如下所示:

//從sunwukong賬戶向shaheshang賬戶轉賬100元!//1.從sunwukong賬戶扣除100元accountDao.update("sunwukong", -100);int i =10/0;//添加一個異常//2.向shaheshang賬戶添加100元accountDao.update("shaheshang", 100);

 



- 在開發中我們的一個業務往往需要同時操作多個表,這些操作往往是不可分割,業務中的對資料庫的多次操作,
要麼同時成功,要麼全都失敗。

- 事務的特性(ACID):
原子性(atomicity)
一個事務是一個不可分割的工作單位,事務中包括的諸操作要麼都做,要麼都不做。

一致性(consistency)
事務必須是使資料庫從一個一致性狀態變到另一個一致性狀態。一致性與原子性是密切相關的。

隔離性(isolation)
一個事務的執行不能被其他事務幹擾。
即一個事務內部的操作及使用的資料對並發的其他事務是隔離的,並發執行的各個事務之間不能互相干擾。

持久性(durability)
持久性也稱永久性(permanence),指一個事務一旦提交,它對資料庫中資料的改變就應該是永久性的。
接下來的其他動作或故障不應該對其有任何影響。


- 操作事務的基本步驟:
1.開啟事務
- 開啟事務以後,我們只後的所有操作將都會在同一個事務當中
2.操作資料庫
- 開啟事務以後再去操作資料庫,所有操作將不會直接提交到資料庫中
3.提交事務
- 將修改應用到資料庫
4.復原事務
- 資料庫操作過程中出現異常了,復原事務,復原事務以後,資料庫變成開啟事務之前的狀態


- mysql中的事務控制
#開啟事務
START TRANSACTION
#復原事務
ROLLBACK
#提交事務
COMMIT

- JDBC中的事務主要通過Connection對象來控制的
1.開啟事務
void setAutoCommit(boolean autoCommit) throws SQLException;
- 設定事務是否自動認可,預設是自動認可
- 設定事務手動提交
conn.setAutoCommit(false);

2.提交事務
void commit() throws SQLException;
- 提交事務
conn.commit()

3.復原事務
void rollback() throws SQLException;
- 復原事務
conn.rollback()

- 事務控制的格式:

//建立一個ConnectionConnection conn = null;try{  //擷取Connection  conn = JDBCUtils.getConnection();  //開啟事務  conn.setAutoCommit(false);  //對資料庫進行操作  //操作成功,提交事務  conn.commit();}catch(Exception e){  e.printStackTrace();  //復原事務  try {    conn.rollback();  } catch (SQLException e1) {    e1.printStackTrace();  }}finally{  JDBCUtils.close(conn, null, null);}

 



- 注意:我們在同一個事務中使用的資料庫連接(Connection)必須是同一個,否則事務還是不作用!
所以此時原來的AcountDAO中的update方法要改為如下所示:

public class AcountDao {  public void update(Connection conn,String name,double money){    //準備兩個變數    PreparedStatement ps = null;    //準備SQL模板    String sql = "UPDATE t_account SET balance = balance + ? WHERE a_name = ?";        try {      //擷取PreparedStatement      ps = conn.prepareStatement(sql);      //填充預留位置      ps.setDouble(1, money);      ps.setString(2, name);          //執行SQL語句      ps.executeUpdate();    } catch (SQLException e) {      // TODO Auto-generated catch block      e.printStackTrace();    }finally{      //此時也不能在這裡關閉資料庫連接了,而是在外邊統一關閉      JDBCUtil.close(null, ps, null);    }  }}

  

Spring架構——批處理(batch)和事務(Transaction)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.