您的位置:首页 > 其它

JDBC进阶之批处理 Batch

2013-11-03 23:03 330 查看
批处理,英文叫 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

<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

DatabaseMetaData md = con.getMetaData();// 得到数据库的元数据

return md.supportsBatchUpdates(); //获取此数据库是否支持批量更新,并返回结果,支持则为true

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

[java] view
plaincopy

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

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

[java] view
plaincopy

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

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

[java] view
plaincopy

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

con.commit(); //提交事务

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

[java] view
plaincopy

sm.close();

con.close();

完整代码如下:

[java] view
plaincopy

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 程序运行结果如下图所示:







内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: