關(guān)于JDBC演示事務(wù)和批處理

這周在學(xué)數(shù)據(jù)庫(kù),以及和JDBC連接數(shù)據(jù)庫(kù)進(jìn)行操作。首先看看JDBC如何處理事務(wù)和批處理吧。

演示事務(wù)

idea中try catch快捷鍵: Ctrl + win + Alt + t

事務(wù)的四大屬性

  1. 原子性(Atomicity):事務(wù)是一個(gè)不可分割的工作單位,事務(wù)中的操作要么都發(fā)生,要么都失敗。
  2. 一致性(Consistency):事務(wù)必須使數(shù)據(jù)庫(kù)從一個(gè)一致性狀態(tài)轉(zhuǎn)換到另一個(gè)一致性狀態(tài)。
  3. 隔離性(Isolation):一個(gè)事務(wù)的執(zhí)行不能被另一個(gè)事務(wù)干擾,即一個(gè)事務(wù)內(nèi)部的操作及使用的數(shù)據(jù)對(duì)并發(fā)的其他事務(wù)是隔離的,并發(fā)執(zhí)行的各個(gè)事務(wù)之間不會(huì)互相干擾。
  4. 持久性(Durability):一個(gè)事務(wù)一旦被提交,它對(duì)數(shù)據(jù)庫(kù)中的數(shù)據(jù)的操作是持久性的,接下來(lái)的其他操作或者數(shù)據(jù)庫(kù)故障都不對(duì)它產(chǎn)生任何影響。

事務(wù)使用步驟

  1. 開啟新事務(wù)

    取消隱式事務(wù)自動(dòng)提交的功能。

  2. 編寫組成事務(wù)的一組sql語(yǔ)句

  3. 結(jié)束事務(wù)

    • commit();提交
    • rollback();回滾

!注意:

開啟事務(wù)的連接對(duì)象和獲取命令的連接對(duì)象必須是同一個(gè)!否則事務(wù)無(wú)效。

使用和不用事務(wù)的區(qū)別

  • 不用事務(wù) : 異常前后的語(yǔ)句執(zhí)行情況不同。只能執(zhí)行異常前的,異常后的無(wú)效。
  • 使用事務(wù) : 可以根據(jù)有無(wú)異常自動(dòng)執(zhí)行提交事務(wù)或回滾。
import com.miyon.jdbc.JDBCUtils;
import org.junit.Test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

/**
 * 演示JDBC中的事務(wù):
 *
 *使用步驟:
 *  1.開啟新事務(wù),取消隱式事務(wù)自動(dòng)提交的功能
 *  setAutoCommit(false);
 *  2.編寫組成事務(wù)的一組sql語(yǔ)句
 *
 *  3.結(jié)束事務(wù)
 *  commit();提交
 *  rollback();回滾
 *
 *  !注意:
 *  開啟事務(wù)的連接對(duì)象和獲取命令的連接對(duì)象必須是同一個(gè)!否則事務(wù)無(wú)效。
 *
 */
public class TestTransaction {
    //不用事務(wù) : 異常前后的語(yǔ)句執(zhí)行情況不同。
    @Test
    public void testNoTransaction() throws Exception{

        //1.獲取連接
        Connection connection = JDBCUtils.getConnection2();
        //2.編寫語(yǔ)句
        PreparedStatement statement = connection.prepareStatement("UPDATE stronginfo SET height=? WHERE id=?");

        //2.1  設(shè)置id為1 的身高為100
        statement.setInt(1,100);
        statement.setInt(2,1);
        statement.executeUpdate();

        int i = 1/0; //模擬異常   異常前面的身高改變,后面的沒(méi)有變化。

        //2.2  設(shè)置id為2 的身高為200
        statement.setInt(1,200);
        statement.setInt(2,2);
        statement.executeUpdate(); 

        //3.釋放資源
        JDBCUtils.close(null,statement,connection);
    }

    
    //使用事務(wù) : 可以根據(jù)有無(wú)異常自動(dòng)執(zhí)行提交事務(wù)或回滾。
    @Test
    public void testTransaction() {
        Connection connection = null;
        PreparedStatement statement = null;
        try {
            //1.獲取連接
            connection = JDBCUtils.getConnection2();

            //2.使用事務(wù)

            //事務(wù)的使用步驟①:開啟事務(wù)
            connection.setAutoCommit(false);//取消事務(wù)自動(dòng)開啟,開啟事務(wù)。

            //事務(wù)的使用步驟②:編寫sql語(yǔ)句并執(zhí)行
            statement = connection.prepareStatement("UPDATE stronginfo SET height=? WHERE id=?");

            //  設(shè)置id為1 的身高為175
            statement.setInt(1,100);
            statement.setInt(2,1);
            statement.executeUpdate();

//            int i = 1/0;
            //模擬異常,使用事務(wù)時(shí),遇到異常,發(fā)生回滾,數(shù)據(jù)沒(méi)有發(fā)生變化。
//            int i = 1/0;
            //沒(méi)有異常時(shí),正常結(jié)束事務(wù),執(zhí)行語(yǔ)句,數(shù)據(jù)發(fā)生變化。

            //  設(shè)置id為2 的身高為205
            statement.setInt(1,99);
            statement.setInt(2,2);
            statement.executeUpdate();

            //事務(wù)的使用步驟③:結(jié)束事務(wù)
            connection.commit();
        } catch (SQLException throwables) {
            try {
                //事務(wù)回滾
                connection.rollback();
            } catch (SQLException e) {
            }
        }finally {
            try {
                JDBCUtils.close(null,statement,connection);
            } catch (Exception e) {
            }
        }
    }
}

批處理

- mysql默認(rèn)批處理是關(guān)閉的,所以我們還需要去打開mysql的批處理:
rewriteBatchedStatements=true
我們需要將以上的參數(shù)添加到mysql的url地址中。

- 注意:低版本的mysql-jdbc驅(qū)動(dòng)也不支持批處理,一般都是在修改的時(shí)候使用批處理,查詢的時(shí)候不使用

相關(guān)API:

  • addBatch();
  • executeBatch();
  • clearBatch();

說(shuō)明:

批處理往往和PreparedStatement一起搭配使用,既可以減少編譯次數(shù),又能減少運(yùn)行次數(shù),大大提高效率!

import com.miyon.jdbc.JDBCUtils;
import org.junit.Test;

import java.sql.Connection;
import java.sql.PreparedStatement;

/**
* 演示批處理的使用
*
* 案例:
* 向admin表中插入50000行數(shù)據(jù);
* 
*
*/
public class TestBatch {
   //不使用批處理
   @Test
   public void testNoBatch() throws Exception {
       //1.獲取連接
       Connection connection = JDBCUtils.getConnection();

       //2.執(zhí)行插入
       PreparedStatement statement = connection.prepareStatement("INSERT INTO admin values(null,?,?)");

       for (int i = 0; i < 50000; i++) {
           statement.setString(1,"john"+i);
           statement.setString(2,"0000");
           //執(zhí)行
           statement.executeUpdate();
       }
       //3.關(guān)閉連接
       JDBCUtils.close(null,statement,connection);
   }

   //使用批處理
   @Test
   public void testBatch() throws Exception{
       //1.獲取連接
       Connection connection = JDBCUtils.getConnection();

       //2.執(zhí)行插入
       PreparedStatement statement = connection.prepareStatement("INSERT INTO admin values(null,?,?)");

       for (int i = 0; i <= 500000; i++) {
           statement.setString(1,"john"+i);
           statement.setString(2,"0000");
           //執(zhí)行
           statement.addBatch();         //將sql語(yǔ)句添加到批處理包中
           if(i%10000==0){                //每1000條執(zhí)行一次
               statement.executeBatch();//執(zhí)行批處理包中的sql語(yǔ)句
               statement.clearBatch();   //清空批處理包中的sql語(yǔ)句
           }
       }
       //3.關(guān)閉連接
       JDBCUtils.close(null,statement,connection);
   }
}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容