批处理,英文叫 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数据库及示例》。代码片段如下:
Connection con = DriverManager.getConnection( "jdbc:mysql://localhost:3306/myuser", "root", "root");
Statement sm = con.createStatement();
2)判断当前使用的JDBC驱动程序和数据库是否批处理。代码片段如下:
DatabaseMetaData md = con.getMetaData();// 得到数据库的元数据
return md.supportsBatchUpdates(); //获取此数据库是否支持批量更新,并返回结果,支持则为true
3)取消 Connection 对象的自动提交模式;代码片段如下:
con.setAutoCommit(false); // 设置连接不自动提交,即用该连接进行的操作都不更新到数据库
4)通过addBatch() 方法添加虚批处理的信息;代码片段如下:
sm.addBatch(sqls[i]); // 将所有的SQL语句添加到Statement中
5)通过executeBatch() 方法执行批处理,并且提交事务;代码片段如下:
int[] batchResultList = sm.executeBatch(); // 将一批命令提交给数据库来执行,并返回更新计数组成的数组。
con.commit(); //提交事务
6)关闭连接;代码片段如下:
sm.close();
con.close();
完整代码如下:
package chp07;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Batch_Executable {
// 利用 JDBC 连接数据库
public static Connection getConnection() {
Connection con = null;
try {
Class.forName("com.mysql.jdbc.Driver"); // 加载Mysql数据驱动
con = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/myuser", "root", "root"); // 创建数据连接
} catch (Exception e) {
System.out.println("数据库连接失败");
}
return con;
}
// 判断当前使用的JDBC驱动程序和数据库是否支持事务处理
public static boolean isBatch(Connection con) {
try {
DatabaseMetaData md = con.getMetaData();// 得到数据库的元数据
return md.supportsBatchUpdates(); //获取此数据库是否支持批量更新,并返回结果,支持则为true
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
// 执行一批SQL语句
public static int[] startBatch(Connection con, String[] sqls)
throws Exception {
if (sqls == null) {
return null;
}
Statement sm = null;
try {
con.setAutoCommit(false); // 设置连接不自动提交,即用该连接进行的操作都不更新到数据库
sm = con.createStatement();
for (int i = 0; i < sqls.length; i++) {
sm.addBatch(sqls[i]); // 将所有的SQL语句添加到Statement中
}
int[] batchResultList = sm.executeBatch(); // 将一批命令提交给数据库来执行,并返回更新计数组成的数组。
con.commit(); //提交事务
return batchResultList; //返回更新计数组成的数组。
} catch (SQLException e) {
e.printStackTrace();
} finally {
sm.close();
}
return null;
}
public static void main(String[] args) throws Exception {
String[] arry = new String[3];// 定义一组事物处理语句
arry[0] = "delete from staff where name='Serein'";
arry[1] = "UPDATE staff SET address='Shenzhen' where name='lili'";// 执行这条语句会引起错误,因为表student中name='lili'不存在
arry[2] = "INSERT INTO staff (name,age,sex,address,depart,worklen,wage) \n"
+ "values ('Serein',39,'M','Beijing','Accountant',6,8800)"; //插入一条员工记录
Connection con = null;
try {
con = getConnection(); // 获得数据库连接
boolean Batch_Flag = isBatch(con); // 判断是否支持批处理
System.out.print("数据库是否支持批量更新? :" + Batch_Flag);
System.out.println(Batch_Flag ? " 支持" : " 不支持");
if (Batch_Flag) {
int[] results = startBatch(con, arry); // 执行一批SQL语句
// 分析执行的结果
for (int i = 0; i < arry.length; i++) {
if (results[i] >= 0) {
System.out.println("语句: " + arry[i] + " 执行成功,影响了" + results[i] + "行数据\n");
} else if (results[i] == Statement.SUCCESS_NO_INFO) {
System.out.println("语句: " + arry[i] + " 执行成功,影响的行数未知\n");
} else if (results[i] == Statement.EXECUTE_FAILED) {
System.out.println("语句: " + arry[i] + " 执行失败\n");
}
}
}
} catch (ClassNotFoundException e1) {
throw e1;
} catch (SQLException e2) {
throw e2;
} finally {
con.close(); // 关闭数据库连接
}
System.out.println("执行批处理后的数据为:");
query();
}
// 查询所有的数据
public static void query() throws Exception {
Connection con = getConnection();
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("select * from staff");
while (rs.next()) { // 判断是否还有下一个数据
// 根据字段名获取相应的值
int ID = rs.getInt("ID"); //ID字段
String name = charset(rs.getString("name")); //name字段
int age = rs.getInt("age"); //age字段
String sex = charset(rs.getString("sex"));
String depart = charset(rs.getString("depart")); //depart字段
String address = charset(rs.getString("address")); //address字段
int worklen = rs.getInt("worklen"); //worklen字段
int wage = rs.getInt("wage"); //wage字段
System.out.println(ID + " " + name + " " + age + " " + sex + " "
+ address + " " + depart + " " + worklen + " " + wage);
}
}
// 字符集的设定为UTF-8
public static String charset(String str) throws Exception {
String newStr = new String(str.getBytes("ISO8859-1"), "UTF-8");
return newStr;
}
}
说明:该Java程序中数据库操作涉及的数据库为 “myuser ” ,并使用其中的 “staff” 表格,也就是我之前的文章《JDBC连接MySQL数据库及示例》里所创建的数据库和表。如果需要跟着去实现并运行这个例子的话,可以前去参考创建,或者根据你自己的数据库情况去修改其中有关连接MySQL的代码以及SQL语句。
附上程序运行前的“staff”表格中的数据:观察其中紫色圈起来的“Serein”这条记录,并与下面程序运行后的结果图对比。
Java 程序运行结果如下图所示:
如果觉得写的还好,顺手“顶”一下哦 ^ ^