JDBC进阶之批处理 Batch

来源:互联网 发布:颖儿怎么瘦下来的知乎 编辑:程序博客网 时间:2024/05/22 00:26

     批处理,英文叫 Batch,顾名思义就是成批地处理某些事务。对于频繁访问数据库的程序而言,选择批处理是最合适不过的了。本文将介绍如何利用 JDBC 实现批处理。


一、什么是批处理

          屁处理是指一次性执行多条SQL语句,并且在执行过程中,如果某条语句出现错误,则仅停止该错误语句的执行,而批处理中其他所有语句则继续执行。这是有别与事务处理 (事务处理的详情参见《JDBC进阶之事务处理基本原理及示例》) 的,事务处理一旦出现错误,则全部都取消执行并进行回滚。

          JDBC API 中提供了批处理的机制,可以让 Statement 同时执行多个 SQL 语句,以提高操作数据库的性能。


二、利用JDBC 实现批处理的基本步骤

          1)创建 Connection 对象,利用 Connection 对象创建 Statement 对象;

          2)判断是否支持批处理;

          3)取消 Connection 对象的自动提交模式;

          4)使用 Statement 对象的增加批处理语句的 addBatch() 方法;

          5)使用 Statement 对象执行批处理的 executeBatch() 方法批处理执行多条添加到 Statement 对象中的 SQL 语句;

          6)关闭连接;


三、批处理应用示例

          根据上述的基本概念和使用方法,接下来通过一个具体的实例来体会上述知识,加深理解。根据利用 JDBC 实现批处理的基本步骤,接下来的示例中对应上述每个步骤的代码片段分解如下:

           1)利用 JDBC 连接数据库,并创建 Connection 对象。这个问题在之前的几篇文章都在重复,不明白之处可前去参考《JDBC连接MySQL数据库及示例》。代码片段如下:

[java] view plaincopy
  1. <div style="text-align: left;">Connection con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/myuser""root""root");</div><div style="text-align: left;">Statement sm = con.createStatement();</div>  

           2)判断当前使用的JDBC驱动程序和数据库是否批处理。代码片段如下:

[java] view plaincopy
  1. DatabaseMetaData md = con.getMetaData();// 得到数据库的元数据              
  2. return md.supportsBatchUpdates();   //获取此数据库是否支持批量更新,并返回结果,支持则为true   


           3)取消 Connection 对象的自动提交模式;代码片段如下:

[java] view plaincopy
  1. con.setAutoCommit(false);   // 设置连接不自动提交,即用该连接进行的操作都不更新到数据库  

           4)通过addBatch() 方法添加虚批处理的信息;代码片段如下:

[java] view plaincopy
  1. sm.addBatch(sqls[i]); // 将所有的SQL语句添加到Statement中  


           5)通过executeBatch() 方法执行批处理,并且提交事务;代码片段如下:

[java] view plaincopy
  1. int[] batchResultList = sm.executeBatch(); // 将一批命令提交给数据库来执行,并返回更新计数组成的数组。  
  2. con.commit();   //提交事务  


           6)关闭连接;代码片段如下:

[java] view plaincopy
  1. sm.close();  
  2. con.close();   

完整代码如下:

[java] view plaincopy
  1. package chp07;  
  2.   
  3. import java.sql.Connection;  
  4. import java.sql.DatabaseMetaData;  
  5. import java.sql.DriverManager;  
  6. import java.sql.ResultSet;  
  7. import java.sql.SQLException;  
  8. import java.sql.Statement;  
  9.   
  10. public class Batch_Executable {  
  11.     // 利用 JDBC 连接数据库  
  12.     public static Connection getConnection() {   
  13.         Connection con = null;  
  14.         try {  
  15.             Class.forName("com.mysql.jdbc.Driver"); // 加载Mysql数据驱动  
  16.             con = DriverManager.getConnection(  
  17.                     "jdbc:mysql://localhost:3306/myuser""root""root"); // 创建数据连接  
  18.         } catch (Exception e) {  
  19.             System.out.println("数据库连接失败");  
  20.         }  
  21.         return con;  
  22.     }  
  23.       
  24.     // 判断当前使用的JDBC驱动程序和数据库是否支持事务处理  
  25.     public static boolean isBatch(Connection con) {  
  26.         try {  
  27.             DatabaseMetaData md = con.getMetaData();// 得到数据库的元数据              
  28.             return md.supportsBatchUpdates();   //获取此数据库是否支持批量更新,并返回结果,支持则为true       
  29.         } catch (SQLException e) {  
  30.             e.printStackTrace();  
  31.         }  
  32.         return false;  
  33.     }  
  34.   
  35.     // 执行一批SQL语句  
  36.     public static int[] startBatch(Connection con, String[] sqls)  
  37.             throws Exception {  
  38.         if (sqls == null) {  
  39.             return null;  
  40.         }  
  41.         Statement sm = null;  
  42.         try {  
  43.             con.setAutoCommit(false);   // 设置连接不自动提交,即用该连接进行的操作都不更新到数据库  
  44.             sm = con.createStatement();  
  45.             for (int i = 0; i < sqls.length; i++) {  
  46.                 sm.addBatch(sqls[i]); // 将所有的SQL语句添加到Statement中  
  47.             }  
  48.             int[] batchResultList = sm.executeBatch(); // 将一批命令提交给数据库来执行,并返回更新计数组成的数组。  
  49.             con.commit();   //提交事务  
  50.               
  51.             return batchResultList; //返回更新计数组成的数组。  
  52.         } catch (SQLException e) {  
  53.             e.printStackTrace();  
  54.         } finally {  
  55.             sm.close();  
  56.         }  
  57.         return null;  
  58.     }  
  59.   
  60.     public static void main(String[] args) throws Exception {  
  61.         String[] arry = new String[3];// 定义一组事物处理语句  
  62.         arry[0] = "delete from staff where name='Serein'";  
  63.         arry[1] = "UPDATE staff SET address='Shenzhen' where name='lili'";// 执行这条语句会引起错误,因为表student中name='lili'不存在  
  64.         arry[2] = "INSERT INTO staff (name,age,sex,address,depart,worklen,wage) \n"  
  65.                 + "values ('Serein',39,'M','Beijing','Accountant',6,8800)"//插入一条员工记录  
  66.         Connection con = null;  
  67.         try {  
  68.             con = getConnection(); // 获得数据库连接  
  69.             boolean Batch_Flag = isBatch(con); // 判断是否支持批处理  
  70.             System.out.print("数据库是否支持批量更新? :" + Batch_Flag);  
  71.             System.out.println(Batch_Flag ? " 支持" : " 不支持");  
  72.             if (Batch_Flag) {  
  73.                 int[] results = startBatch(con, arry); // 执行一批SQL语句  
  74.                 // 分析执行的结果  
  75.                 for (int i = 0; i < arry.length; i++) {  
  76.                     if (results[i] >= 0) {  
  77.                         System.out.println("语句: " + arry[i] + " 执行成功,影响了" + results[i] + "行数据\n");  
  78.                     } else if (results[i] == Statement.SUCCESS_NO_INFO) {  
  79.                         System.out.println("语句: " + arry[i] + " 执行成功,影响的行数未知\n");  
  80.                     } else if (results[i] == Statement.EXECUTE_FAILED) {  
  81.                         System.out.println("语句: " + arry[i] + " 执行失败\n");  
  82.                     }  
  83.                 }  
  84.             }  
  85.         } catch (ClassNotFoundException e1) {  
  86.             throw e1;  
  87.         } catch (SQLException e2) {  
  88.             throw e2;  
  89.         } finally {  
  90.             con.close(); // 关闭数据库连接  
  91.         }  
  92.         System.out.println("执行批处理后的数据为:");  
  93.         query();  
  94.     }  
  95.       
  96.     // 查询所有的数据  
  97.     public static void query() throws Exception {   
  98.         Connection con = getConnection();  
  99.         Statement st = con.createStatement();  
  100.         ResultSet rs = st.executeQuery("select * from staff");  
  101.         while (rs.next()) { // 判断是否还有下一个数据  
  102.             // 根据字段名获取相应的值  
  103.             int ID = rs.getInt("ID");   //ID字段  
  104.             String name = charset(rs.getString("name"));    //name字段  
  105.             int age = rs.getInt("age");     //age字段  
  106.             String sex = charset(rs.getString("sex"));  
  107.             String depart = charset(rs.getString("depart"));    //depart字段  
  108.             String address = charset(rs.getString("address"));  //address字段  
  109.             int worklen = rs.getInt("worklen");     //worklen字段  
  110.             int wage = rs.getInt("wage");       //wage字段  
  111.             System.out.println(ID + " "  + name + " " + age + " " + sex + " "  
  112.                     + address + " " + depart + " " + worklen + " " + wage);  
  113.         }  
  114.     }  
  115.       
  116.     // 字符集的设定为UTF-8  
  117.     public static String charset(String str) throws Exception {  
  118.         String newStr = new String(str.getBytes("ISO8859-1"), "UTF-8");  
  119.         return newStr;  
  120.     }  
  121.   
  122. }  

说明:该Java程序中数据库操作涉及的数据库为 “myuser ” ,并使用其中的 “staff” 表格,也就是我之前的文章《JDBC连接MySQL数据库及示例》里所创建的数据库和表。如果需要跟着去实现并运行这个例子的话,可以前去参考创建,或者根据你自己的数据库情况去修改其中有关连接MySQL的代码以及SQL语句。

附上程序运行前的“staff”表格中的数据:观察其中紫色圈起来的“Serein”这条记录,并与下面程序运行后的结果图对比。

Java 程序运行结果如下图所示:




原创粉丝点击