Mysql Statement 批處理異常

好記憶不如爛筆頭,能記下點東西,就記下點,有時間拿出來看看,也會發覺不一樣的感受.

業務背景:接一個徵信公司的api,然後快速解析,批量入庫的操作!記錄一下流水賬,主要是記錄關於Statement執行批處理操作,sql後邊不允許加";"的異常 !!!

目錄

梳理

1.Jdbc連接池代碼 :

2. jdbc url 配置 

4.結論

5.總結


梳理

1. api 返回的是 json 串;

2.快速解析json,生成建表語句,並且批量插入(個別接口,返回解析,拼裝後的sql語句達到:5w+)

3.使用DruidDataSource 構建jdbc連接池,使用 Statement  的批處理操作.

執行:

1.Jdbc連接池代碼 :

private Logger logger = LoggerFactory.getLogger(getClass().getName());
/**
 * 數據庫集合.
 */
final ConcurrentHashMap<String, DataSource> dataSourceMap = new ConcurrentHashMap();
/**
 * 初始化池子
 * @param destDbInfo
 */
public boolean initPool(DestDbInfo destDbInfo){
   try {
      //通過直接創建連接池對象的方式創建連接池對象
      DruidDataSource druidDataSource = new DruidDataSource();
      druidDataSource.setUsername(destDbInfo.getUsername());
      druidDataSource.setPassword(destDbInfo.getPassword());
      druidDataSource.setUrl(destDbInfo.getUrl());
      druidDataSource.setDriverClassName(destDbInfo.getDriver());
      druidDataSource.setMinIdle(10);
      druidDataSource.setMaxActive(300);
      DataSource druidPool = druidDataSource;
      String key = JsonUtils.bean2JsonStr(destDbInfo);
      dataSourceMap.put(key,druidPool);
      return true;
   }catch (Exception e){
      e.printStackTrace();
   }
   return false;
}

/**
 * 得到數據庫連接
 */
public Connection getConn(DestDbInfo destDbInfo){
   if (destDbInfo==null){
      logger.error("傳遞的對象爲空!");
      return null;
   }
   String key = JsonUtils.bean2JsonStr(destDbInfo);
   DataSource druidPool = dataSourceMap.get(key);
   try {
      if (druidPool!=null){
         return druidPool.getConnection();
      }
   }catch (Exception e){
      e.printStackTrace();
   }
   return null;
}

/**
 * 執行入庫操作.
 * @param destDbInfo
 * @param sqls
 * @return
 */
public boolean executeSql(DestDbInfo destDbInfo,List<String> sqls) throws SQLException {
   if (sqls.isEmpty()){
      return false;
   }
   Connection connection = getConn(destDbInfo);
   Statement statement = connection.createStatement();
   int count = sqls.size();
   for (int i = 0; i < count ; i++) {
      System.out.println(sqls.get(i));
      statement.addBatch(sqls.get(i));
      if (i>0 && i % 10000 ==0){
         statement.executeBatch();
         statement.clearBatch();
      }
   }
   int[] nums = statement.executeBatch();
   System.out.println("執行成功的條數是:"+nums);
   statement.clearBatch();
   statement.close();
   connection.close();
   return true;
}

/**
 * 執行單條件語句
 * @param destDbInfo
 * @param sql
 * @return
 * @throws SQLException
 */
public boolean executeSql(DestDbInfo destDbInfo,String sql) throws SQLException {
   if (StringUtils.isBlank(sql)){
      return false;
   }
   Connection connection = getConn(destDbInfo);
   PreparedStatement statement = connection.prepareStatement(sql);
   int count = statement.executeUpdate();
   statement.close();
   connection.close();
   return count>0 ? true : false;
}

/**
 * 使用PreparedStatement查詢數據
 * @param destDbInfo
 * @param sql
 * @return 結果集   不要關閉連接
 */
public Integer selectSql(DestDbInfo destDbInfo,String sql){
   try {
      Connection connection = getConn(destDbInfo);
      PreparedStatement pstmt=connection.prepareStatement(sql);
      ResultSet rs = pstmt.executeQuery();
      Integer value =null;
      while (rs.next()){
         value=rs.getInt(1);
      }
      rs.close();
      pstmt.close();
      connection.close();
      return value;
   } catch (SQLException e1) {
      logger.error(e1.getMessage());
   }
   return null;
}

2. jdbc url 配置 

jdbc:mysql://192.168.10.186:3306/data_sync?autoReconnect=true&amp;rewriteBatchedStatements=true&amp;useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=false

mysql中,如果不加上rewriteBatchedStatements=true,你的批處理是假的批處理,只是寫了批處理,但是jdbc去執行的時候,卻不是按照批處理來執行的。

 

3. 執行異常,要執行的 sql 如:

可以看見,所有的sql後邊都是加上";"的,這就會報上面的錯誤,讓人哭笑不得、因爲在oracle中,sql語句後邊要是不加";",那執行是要報錯的。

 

4.結論

哎,真的是一個坑爹的潛藏的異常信息,一般人誰會想到:正常的sql都會寫";",可是在mysql的批處理上,就會報錯,而且這種錯誤很難定位的到是因爲分號的問題。

 

5.總結

使用rewriteBatchedStatements 是有限制的,即爲執行的總條數>3,如果小於這個數,那麼還是走的是逐條執行!真的是坑!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章