天天看點

Java通過JDBC向資料庫批量插入資料(MySQL為例)

注:本文僅供學習參考,作者水準有限,如有錯誤還請指正!

文章目錄

  • ​​1、 JDBC的批量處理語句:​​
  • ​​2、批量指向SQL語句的情況:​​
  • ​​3、關于本案例的注意事項:​​
  • ​​4、驅動程式​​
  • ​​5、案例源碼​​

         ​​在資料庫中需要大量插入或更新記錄時,可以使用java的批量更新機制,這一機制允許多條語句一次性送出給資料庫批量處理。​​

1、 JDBC的批量處理語句:

  • addBatch(String):添加需要批量處理的SQL語句或是參數;
  • executeBatch():執行批量處理語句;
  • clearBatch():清空緩存的資料

2、批量指向SQL語句的情況:

  • 多條SQL語句的批量處理
  • 一個SQL語句的批量處理

3、關于本案例的注意事項:

  • 該案例中使用的MySQL版本為8.0.x,故對應的mysql-connection-java驅動應為8.0.x
  • 5.x版本的驅動使用的驅動路徑為:com.mysql.jdbc.Driver, 8.x版本的驅動路徑為com.mysql.cj.jdbc.Driver
  • 在本案例的三、四中方式中使用了java的批處理(Batch),MySQL伺服器預設是關閉的,我們需要通過一個參數,讓mysql開啟批處理支援。即,在配置檔案的url後面加上參數“&rewriteBatchedStatements=true”。如下:

    user=root

    password=abc123

    url=jdbc:mysql://localhost:3306/test?characterEncoding=utf8&useUnicode=true&rewriteBatchedStatements=true

    driverClass=com.mysql.cj.jdbc.Driver

  • 有關資料庫的連接配接、插入等操作可參考博文

    4、驅動程式

    • 我使用的驅動程式為8.0.27版本,官網下載下傳:​​MySQL :: Download MySQL Connector/J (Archived Versions)​​
      Java通過JDBC向資料庫批量插入資料(MySQL為例)
    • 使用方式:将mysql-connectior-java-8.0.27.jar解壓至lib檔案夾下加載即可
      Java通過JDBC向資料庫批量插入資料(MySQL為例)

    5、案例源碼

    • 實驗使用的表結構:
    CREATE TABLE goods(
      id INT PRIMARY KEY AUTO_INCREMENT,
      NAME VARCHAR(25)
    );      
    • java源碼
    package com.Etui5.blob;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.Statement;
    
    import org.junit.Test;
    
    import com.Etui3.util.JDBCUtils;
    
    /**
     * 使用PreparedStatement實作批量資料的操作
     * 
     * update、delete本身就具備批量操作的效果
     * 此時的批量操作主要指的是批量插入。使用PreparedStatement實作更高效的批量操作
     * 
     * 方式一:使用Statement
     * 
     *
     */
    public class insertTest {
      
      // 批量插入資料方式一:使用Statement
    //  @Test 
      public void testInsert1() throws Exception {
        Connection conn = JDBCUtils.getConnection();
        Statement st = conn.createStatement();
        for(int i = 0; i < 20000; i++) {
          String sql = "insert into goods(name) values('nmae_" + i + "')";
          st.execute(sql);
        }
        conn.close();
        st.close();
      }
      
      // 方式二:使用PreparedStatement
    //  @Test
      public void testInsert2() {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
          long start = System.currentTimeMillis();
          conn = JDBCUtils.getConnection();
          String sql = "insert into goods(name) values(?)";
          ps = conn.prepareStatement(sql);
          for(int i = 0; i < 20000; i++) {
            ps.setObject(1, "name_" + i);
            ps.execute();
          }
          
          long end = System.currentTimeMillis();
          
          System.out.println("花費時間為:" + (end - start) + "ms"); // 20000條:51188ms
        } catch (Exception e) {
          e.printStackTrace();
        } finally {
          JDBCUtils.closeResource(conn, ps);      
        }
      }
      
      // 方式三:
      // 1、批量處理方式:addBatch(), executeBatch(), clearBatch()
      // 2、mysql 伺服器預設是關閉批處理的,我們需要通過一個參數,讓mysql開啟批處理支援
      //      ?rewriteBatchedStatements=true寫在配置檔案的url後面
      // 3、使用更新的mysql驅動:5.1.37,該驅動需與mysql的版本對應,我使用的為8.0.27
      // 4、以往練習使用的都是5.1.7驅動,連接配接驅動為com.mysql.jdbc.Driver,8.0.x版本需改為com.mysql.cj.jdbc.Driver
    //  @Test
      public void testInsert3() {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
          long start = System.currentTimeMillis();
          conn = JDBCUtils.getConnection();
          String sql = "insert into goods(name) values(?)";
          ps = conn.prepareStatement(sql);
          for(int i = 0; i < 1000000; i++) {
            ps.setObject(1, "name_" + i);
    //        ps.execute();
            
            // 每插入500條插入一次
            // 添加到批處理
            ps.addBatch();
            if(i % 500 == 0) {
              // 執行批量操作
              ps.executeBatch();
              // 清空batch
              ps.clearBatch();
            }
          }
          
          long end = System.currentTimeMillis();
          
          System.out.println("花費時間為:" + (end - start) + "ms"); // 20000條:349ms,1000000條:15833ms
        } catch (Exception e) {
          e.printStackTrace();
        } finally {
          JDBCUtils.closeResource(conn, ps);      
        }
      }
      
      // 方式四: 
      // 将自動送出關閉
      @Test
      public void testInsert4() {
        Connection conn = null;
        PreparedStatement ps = null;
        try {
          long start = System.currentTimeMillis();
          conn = JDBCUtils.getConnection();
          
          conn.setAutoCommit(false);// 關閉自動送出
          
          String sql = "insert into goods(name) values(?)";
          ps = conn.prepareStatement(sql);
          for(int i = 0; i < 1000000; i++) {
            ps.setObject(1, "name_" + i);
            ps.addBatch();
            if(i % 500 == 0) {
              ps.executeBatch();
              ps.clearBatch();
            }
          }
          
          conn.commit();// 預處理完成後統一送出
          
          long end = System.currentTimeMillis();
          
          System.out.println("花費時間為:" + (end - start) + "ms"); // 1000000條:9505ms
        } catch (Exception e) {
          e.printStackTrace();
        } finally {
          JDBCUtils.closeResource(conn, ps);      
        }
      }
    }