首页 > 代码库 > JDBC规范(转)
JDBC规范(转)
公司开发一直用的是ibatis,进来心血来潮想研究一下源码,可是发现自己的JDBC似乎已经忘得差不多了,为了自己能顺利的研读ibatis的源码,于是乎找到了 XIAO_DF的JDBC规范的博客,转到自己博客方便阅读,感谢技术老铁的分享!
JDBC接口规范
前言
JDBC(JavaDatabase Connectivity)表示Java查询引擎连接,由一组用Java编程语言编写的类和接口组成。JDBC为Java程序访问关系型查询引擎提供了编程接口,为查询引擎开发人员提供了一个标准的API,使他们能够用JavaAPI 来编写查询引擎应用程序,而不必为访问不同查询引擎编写不同的程序。
随着J2SE版本的不断发展,JDBC规范也不断完善。发展到目前为止,JDBC规范已经发到3.0版本。该版本相对于以前的2.0版本又提供了很多新的特性,比如保存点、查询计划的参数信息、多结果集、自动生成键等。
查询引擎 JDBC驱动程序基本实现了JDBC3.0规范,尤其针对JDBC3.0规范中的新增特性,给出了很好的支持。对于这些新的特性的支持,为用户提供了更为方便的编写查询引擎应用程序的方法,使得用户编写应用程序将更加高效,编写的应用程序也更加健壮。
本规范结合查询引擎的特点,针对JDBC 的基本概念和基本技术,定义查询引擎JDBC标准规范。
本规范适用于所有查询引擎的用户。
1.2.1 建立连接
打开一个与查询引擎的连接,需要调用DriverManager.getConnection()方法。通过调用该方法,可以取得一个Connection类的实例(Instance),这个实例就在应用程序和查询引擎建立了一个连接,使用这个连接,我们就能通过查询引擎系统操作各个节点了。要得到Connection的实例,就需要应用程序输入用户名、密码、查询引擎 JDBC驱动特定的连接语句以及想要连接的查询引擎库名称。用户将有两种连接方法来与查询引擎建立连接。
1. 指定URL、用户名和密码
下面这个方法用URL、用户名、密码作为参数:
Class.forName(“com.scistor.swift.jdbc.Driver”);
getConnection(String URL, String user, Stringpassword);
URL的格式是:
jdbc:swift://host/database
jdbc:swift://host:port/database
其中:
参数 |
参数说明 |
host |
服务器的主机名。 |
port |
服务器监听的端口号。缺省时是查询引擎默认的端口号(2003) |
database |
查询引擎库名。此处的database就是在安装时创建的查询引擎库所对应的名字 |
比如想要连接查询引擎,它的URL、用户名、密码分别是:
Stringurl = “jdbc:swift://localhost/SYSTEM”;
Stringname = “SYSDBA”;
Stringpassword = “SYSDBA”;
那么就可以很容易的获得一个与查询引擎的连接了
Connectioncon = DriverManager.getConnection(url,name,password);
这就意味着用户通过用户名”SYSDBA”,密码”SYSDBA”连接到了本地的名称为“SYSTEM”的查询引擎。
2. 指定URL和Properties对象
指定URL的方法同上面一样,现在我们就来指定Properties对象:
java.util.Properties info = newjava.util.Properties();
info.setProperty(“user”,”SYSDBA”);
info.setProperty(“password”,”SYSDBA”);
现在就可以获得连接了:
Connection con =DriverManager.getConnection(url,info);
1.2.2 创建Statement对象
一旦连接上了查询引擎,也就是说,已经获得了一个Connection的实例,那么就可以通过该Connection实例创建一个Statement对象。通过Statement对象来处理不同的SQL语句。我们就用前面获得的Connection实例con来创建一个Statement对象,下面就是一个创建Statement对象的例子:
Statement stmt = con.createStatement();
这个操作是完全遵循JDBC标准规范的,没有任何要处理关于特定查询引擎 JDBC驱动的地方。
1.2.3 执行语句
如果需要查询查询引擎中的数据,只需要调用Statement对象的executeQuery()方法。这个方法以SQL语句作为参数,方法执行完后返回一个JDBC的ResultSet对象。为了保持连续性,我们就使用上面已经创建的Statement对象。比如我们要从一张表名为TEMP的表中选出所有数据,我们只要简单的调用executeQurey()方法:
ResultSet rs = stmt.executeQuery(“SELECT * FROMTEMP”);
同上面一样,这个操作也是完全遵循JDBC标准规范的,没有任何要处理关于特定查询引擎 JDBC驱动的地方。
注:假如我们已经在查询引擎中创建了一个名为TEMP的表,它有两列分别为ID(INT),VALUE(STRING)。后面的章节将多次使用到这个表。
1.2.4 处理结果集
一旦执行了SQL语句,获得了ResultSet对象,那么就可以通过调用Resulset对象中的next()操作遍历ResultSet操作,以获得每条记录。如果next()方法返回为true,那么就意味着现在有记录可以读取出来,接着就可以调用ResultSet对象的getXXX()方法来取得对应列的值,XXX代表了要取得的列的类型,该方法是以列序号或列名为参数的,下面就从上面获得的ResultSet对象中取得数据:
while (rs.next())
System.out.println(rs.getString(2));
在这里TEMP表中第二列的类型STRING,所以我们使用了rs对象的getString()方法。当然这里也可以通过调用rs.getString(paramName)来获得值。这个方法也是遵循JDBC标准的。如果一直向下做遍历,当没有记录的时候,next()就会返回false。
1.2.5 关闭Statement对象和结果集
当不再需要使用Statement和Resultset数据之后,就必须显式的关闭已经创建的Statement对象。JDBC驱动程序没有自动地释放这些对象的功能,应用程序必须显式的调用Statement的close()方法和ResultSet的close()方法。一旦已经显式的关闭了已经创建的对象,就不能再使用这些对象了。如果已经不再使用某些Statement对象和Resultset对象,但是却不去释放它,那将会造成严重的内存泄漏。如果创建了大量的Statement和ResultSet对象,但是却不释放它们,应用程序可能最终会造成OUT OF MEMORY的后果。
比如应用程序中的Statement对象是stmt,ResultSet对象是rs,就可以这样关闭它:
rs.close();
stmt.close();
虽然关闭了Statement对象时,创建该Statement对象的Connection仍然与查询引擎保持连接,应用程序仍然可以用它创建其他的Statement对象。
1.2.6 关闭与查询引擎的连接
最后,当不再需要与查询引擎的连接时,就需要关闭Connection对象。调用Connection的close()方法,就会关闭连接,释放网络上的资源。
con.close();
1.3数据类型的映射
JDBC驱动支持大多数由JDBC3.0规范所要求的类型。在类型映射中,我们将讨论JAVA类型、JDBC类型以及查询引擎类型是如何进行相互映射的。比如前台的String对应于JDBC类型中的那种,又对应于查询引擎中的那种类型。
表3-1是查询引擎数据类型。
序号 |
类型 |
描述 |
有效范围 |
1 |
smallint |
整型数据 |
[-32768, 32767] |
2 |
int |
整型数据 |
[-2147483648, 2147483647] |
3 |
bigint |
整型数据 |
[-9223372036854775808, 9223372036854775807] |
4 |
double precision |
浮点双精度数 |
[2.2250738585072014e-308,1.7976931348623158e+308] |
5 |
real |
浮点精度数字 |
[-1E+308, 1E+308] |
6 |
text |
可变长度的字符数据 |
最大长度为1G个字符 |
7 |
char(n) |
定长字符串 |
长度为n |
8 |
varchar(n) |
变长字符串 |
最大长度为n |
9 |
bytea |
变长的二进制字串 |
理论上没有限制,可以达到4个G |
10 |
boolean |
布尔类型 |
TRUE/FALSE |
11 |
timestamp |
时间戳 |
‘2013-01-01 00:00:00’ |
查询引擎数据类型这一列列举了在查询引擎中的数据类型。
JDBC 类型这一列列举JDBC标准支持的,并在java.sql.Types类中有定义的类型。
标准JAVA类型这一列列举了在JAVA语言中定义的标准类型。
表3-2 查询引擎数据类型、JDBC类型和标准JAVA类型之间的映射。
序号 |
查询引擎 数据类型 |
JDBC类型 |
标准JAVA类型 |
1 |
smallint |
java.sql.Types.SMALLINT |
short |
2 |
Int |
java.sql.Types.INT |
int |
3 |
Bigint |
java.sql.Types.BIGINT |
long |
4 |
double precision |
java.sql.Types.DOUBLE |
double |
5 |
Real |
java.sql.Types.FLOAT |
double |
6 |
Text |
java.sql.Types.VARCHAR |
java.lang.String |
7 |
char(n) |
java.sql.Types.VARCHAR |
java.lang.String |
8 |
varchar(n) |
java.sql.Types.VARCHAR |
java.lang.String |
9 |
bytea |
java.sql.Types.BINARY |
byte[] |
10 |
boolean |
java.sql.Types.BOOLEAN |
boolean |
11 |
timestamp |
java.sql.Types.TIMESTAMP |
java.sql.Timestamp |
1.4处理SQL异常
在运行应用程序的时候,可能会抛出很多异常。可能由于查询引擎没有打开导致连接不上,插入的数据类型不符,想要删除的表不存在等等。由JDBC抛出的异常大多是java.sql.SQLException或者它的子类的对象。这些异常有可能是从查询引擎中抛出来的,也有可能是从前台的JDBC驱动抛出的。比如上面提到的服务器连接不上就是由JDBC驱动抛出的异常,想要删除的表不存在就是由查询引擎中抛出的错误。
那么如何处理这些由JDBC抛出的异常呢?由JDBC抛出的java.sql.SQLException和它的子类,一般都会包括错误描述,标准的SQL State和厂商特定的错误编码。错误描述、SQL State和错误编号会在附录中给出。
java.sql.SQLException提供了获取这些信息的方法。
通过调用SQLException的getMessage()方法,可以获得由JDBC驱动或者查询引擎报出的错误。通过这个错误描述,就可以知道错误的原因了。
通过调用SQLException的getErrorCode()方法,可以获得由厂商特定错误编码,在有些情况下可能不返回错误描述,只返回一个空的字符串。
通过调用SQLException的getState()的方法,可以获得标准的SQL State。SQL State是由5个数字组成的字符串。
下面这例子打印出调用getMessage方法所得到的错误信息。
try{
<somecode>
}
catch(SQLException se){
System.out.println(“错误信息:”+se.getMessage());
}
SQLException类也允许打印出堆栈式的出错信息。打印的内容将包括错误描述,和这个错误从抛出一直到被捕捉到所经过的所有被调用的方法。
下面给出了如何打印出堆栈信息的方法。
try{
<somecode>
}
catch(SQLException se){
se.printStackTrace();}
第2章 查询引擎 JDBC驱动对于 JDBC规范的支持
查询引擎 JDBC驱动是基于JDBC3.0规范而实现的。在以前的JDBC2.0规范中,将API分为核心API和扩展API。JDBC3.0规范包含了JDBC2.0规范的核心API以及JDBC2.0的扩展API,并添加了一些新的特性。查询引擎 JDBC驱动实现了JDBC3.0规范中的大部分接口,主要包括下列接口:
l java.sql.Dirver
l java.sql.Connection
l java.sql.Statement
l java.sql.ResultSet
l java.sql.DatabaseMetaData
l java.sql.ResultSetMetaData
查询引擎 JDBC驱动对于上述每个接口的方法,基本上提供了实现。除了JDBC要求的基本特性之外,比如执行一般的SQL语句,可以对从结果集取得数据等,遵照JDBC3.0的规范,查询引擎 JDBC驱动还提供了一些JDBC的特殊特性:
按照JDBC规范,提供了类型之间的相互转换,比如int和String之间的转化,String和java.sql.Date之间的转化,具体的内容,请参照《JDBC3.0规范》
实现了对ResultSet的各种特性的支持,这些特性是在创建Statement对象、PreparedStatement对象和CallableStatement对象时指定的。
Type包括:
l TYPE_FORWARDONLY
Concurrency包括:
l CONCUR_READ_ONLY
Holdability包括:
l 不支持
在查询引擎 JDBC驱动中对这些特性都给出了较好的实现。具体说明将在结果集一章中给出。
允许用户在Statement和ResultSet中设置fetchSize,通过设置fetchSize,对于记录数很大的情况下,可以极大的降低对内存的使用量。
第3章 执行SQL语句和处理结果集
查询引擎 JDBC驱动提供了Statement对象用于发送SQL语句到查询引擎。
3.1创建Statement对象
建立了到查询引擎的连接之后,就可以使用该连接发送SQL语句。Statement对象通过Connection接口的方法createStatement创建,例如:
Connection conn = DriverManager.getConnection(url,"SYSDBA","SYSDBA");
Statement stmt = conn.createStatement();
在创建Statement对象的时候,可以通过参数来指定产生结果集的属性,详见“结果集处理”一章。为了执行Statement对象,被发送到查询引擎的SQL语句将被作为参数提供给Statement的方法,例如:
String sql = “SELECT * FROM TEMP”;
ResultSet rs = stmt.executeQuery(sql);
3.2使用Statement对象执行SQL语句
Statement接口提供了三种执行SQL语句的方法:executeQuery、executeUpdate和execute。使用哪一个方法由SQL语句执行后产生的结果而决定。
方法executeQuery用于产生单个结果集的语句,例如SELECT语句,执行executeQuery方法将返回一个结果集对象。方法executeUpdate用于执行INSERT、UPDATE或DELETE语句以及SQL DDL(数据定义语言)语句,例如CREATE TABLE和DROP TABLE。由于INSERT、UPDATE或DELETE语句的效果是修改表中若干行中的一列或多列,所以executeUpdate的返回值是一个整数,指示受影响的行数(即更新记录数);对于CREATETABLE或DROP TABLE等不操作行的语句,executeUpdate的返回值总是为零(我们把这个零返回值也视为更新记录数,即没有记录受到影响)。当被执行的SQL语句返回一个更新记录数、一个结果集、多结果集或者SQL语句的类型未知,则使用execute方法。下面的例子演示了以上方法的使用。
使用executeQuery方法处理SQL数据查询语句:
Statement stmt = conn.createStatement();
String sql = “SELECT ID,VALUE FROM TEMP”;
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()){
// 处理获得的数据记录
}
使用executeUpdate方法处理SQL数据操纵语句:
Statement stmt = conn.createStatement();
String sql = “UPDATETEMPSETVALUE = http://www.mamicode.com/‘VALUE10’WHEREID = 10”
int rows = stmt.executeUpdate(sql);
if (rows >= 0) {
//<some code>
}
使用executeUpdate方法处理SQL数据定义语句:
Statement stmt = conn.createStatement();
String sql = “CREATE TABLE TEST(ID INT, VALUEVARCHAR(50))”;
int updcount = stmt.executeUpdate(sql);
if (updcount== 0) {
// <some code>
}
使用execute方法处理SQL语句:
String sql;
// 对字符串sql进行赋值,单条SQL语句
...
Statement stmt = conn.createStatement();
boolean b = stmt.execute(sql);
if (b) {
// 说明返回的是ResultSet对象
ResultSet rs;
rs = stmt.getResultSet();
while (rs.next()) {
//<some code>
}
}
else {
// 说明返回的是更新记录数
int rows = stmt.getUpdateCount();
if (rows >= 0) {
//<somecode>
}
}
需要说明的是,执行上面提及的任一种方法都将关闭所调用的Statement对象的当前打开结果集(如果存在)。这意味着在重新执行Statement对象之前,需要完成对当前ResultSet对象的处理。
3.3使用execute()方法
当SQL语句执行后会返回ResultSet对象或更新记录数,通常使用execute方法。当同时执行多个SQL语句、执行某个存储过程或动态执行未知SQL字符串(即应用程序程序员在编译时未知)时,就有可能出现多个结果的情况,因此在这种情况下就需要使用execute(),因为execute()方法同时适用于对有ResultSet对象返回和有更新记录数返回的情况。
如果不知道返回结果的类型,则可以通过execute方法的返回值来进行判断。如果结果是ResultSet对象,则方法execute返回true;如果结果类型是更新纪录数,则返回false。如果返回int,则意味着结果是更新记录数或执行的语句是DDL命令。在调用方法execute之后可以调用getResultSet()或getUpdateCount()。其中getResultSet()方法获得当前结果集,而getUpdateCount()获得记录的更新数。
当SQL语句的返回结果不是结果集时,则方法getResultSet将返回null。这可能意味着结果是一个更新记录数或没有其它结果。在这种情况下,判断null真正含义的方法是调用方法getUpdateCount(),它将返回一个整数。这个整数为调用语句所影响的行数;如果为-1则表示结果是结果集或没有结果。如果方法getResultSet已返回null(表示结果不是ResultSet对象),则返回值-1表示没有其它结果。也就是说,当下列条件((stmt.getResultSet()==null)&&(stmt.getUpdateCount()==-1))为真时表示没有结果(或没有其它结果)。
下面给了一个示例,用于执行未知sql语句的情况下作判断:
boolean retVal = stmt.execute( sql);
if (retVal){
//有结果集返回
ResultSet rs = stmt.getResultSet();
//处理结果集
//<somecode>
}
else {
//说明可能有更新记录
intupdateCount = stmt.getUpdateCount();
if(updateCount != -1) {
//对有更新记录的情况作处理
//<somecode>
}
}
3.4关闭Statement对象
作为一种好的编程风格,对于不再使用的Statement对象应显式地关闭它们,这可以使得Statement对象使用的外部资源立即被释放。同时,应显示关闭由Statement对象所创建的Resultset对象,但是ResultSet对象使用的资源只有到垃圾收集机制启动时,才会真正的释放他们。所以,当一个对象不需要时,无论是ResultSet对象还是Statement对象,都应该尽早地释放他们。
第4章 结果集(ResultSet)的特性
本章内容包括:
4.1概述
在JDBC3.0规范中结果集的特性,包括可滚动性(scrollability)、可定位(positioning)、敏感性(sensitivity)、可更新性(updatability)和可保持性(holdability)。这些特性可以分为Type,Concurrency和Holdability三大类,下表为查询引擎对各特性的支持情况定义:
ResultSet Types |
支持程度 |
ResultSet Concurrency |
支持程度 |
ResultSet Holdability |
支持程度 |
TYPE_FORWARD_ONLY |
支持 |
CONCUR_READ_ONLY |
支持 |
HOLD_CURSOR_OVER_COMMIT |
不支持 |
TYPE_SCROLL_INSENSITIVE |
不支持 |
CONCUR_UPDATABLE |
不支持 |
CLOSE_CURSOR_AT_COMMIT |
不支持 |
TYPE_SCROLL_SENSITIVE |
不支持 |
|
|
|
|
4.2设置结果集大小
查询引擎 JDBC驱动提供了允许用户设置结果集大小(即上面结果集的敏感性中提到的窗口的大小)的方法。通过设置结果集的大小,驱动每次从查询引擎取得的记录数将不超过用户设置的大小。比如TEMP表的实际记录数有100万条,用户如果把它一次全部取出来,就会耗用大量的内存;用户可以设置结果集的大小,比如为1万,那么查询引擎 JDBC驱动将每次只从后台查询引擎取1万条。当用户作游标移动操作时,如果JDBC发现那条记录还没从查询引擎取出来,就会从查询引擎取出那条记录。
stmt.setFetchSize(10000);
ResultSet rs = stmt.executeQuery(“SELECT * FROMTEMP”);
while(rs.next()) {
//如果调用到第10001次,驱动程序会再从后台取10000条,把原来的记录
//覆盖掉,这样内存中始终只是用了10000条记录内存的大小
}
在缺省情况下,即用户不设fetchSize时, JDBC驱动会将所有记录一次取出来。因此对于记录数极大的情况下(比如100万条)可能会耗用大量的内存。但是如果用户将fetchSize设得不够大,会增加网络的开销和查询引擎的查询操作,因此在这种情况下应用程序的执行速度将不如缺省的情况。用户对于内存耗用量和执行速度必须有一个折中的考虑,取得最好的平衡点。
第5章 MetaData信息
MetaData是一种重要的机制,可以供用户来获取相应对象(目标数据源、结果集,参数信息等)的详细描述信息。在JDBC驱动中,有三个接口专门提供相应的MetaData信息:
DatabaseMetaData:用于描述查询引擎的元数据信息;
ResultSetMetaData:用于描述ResultSet对象的元数据信息;
ParameterMetaData:用于描述PreparedStatement、CallableStatement对象参数属性的元数据信息。
下面将分别介绍这三个接口相应方法的使用。
5.1DatabaseMetaData
DatabaseMetaData接口的实现是为了给用户提供目标数据源的信息,应用程序根据接口中的各种方法得到相应的信息,进而决定如何与之交互。
获取DatabaseMeta信息的步骤是:首先创建DatabaseMetaData对象:
DatabaseMetaData dbmd = conn.getMetaData();
利用dbmd对象,调用DatabaseMetaData接口的相应方法就可以获得查询引擎和JDBC驱动程序的一些信息,例如:
int majorVersion = dbmd.getJDBCMajorVersion(); // 获得JDBC 驱动程序的主版本号
DatabaseMetaData接口包括了超过150种的方法,根据提供信息的类型,可以把这些方法分为五类:
提供数据源总体信息的方法:比如获得查询引擎的主版本号版本信息的getDatabaseMajorVersion();
说明数据源是否支持某一特定特征的方法:比如根据方法supportsANSI92EntryLevelSQL()的返回值可以知道查询引擎是否支持ANSI92入门级SQL语法;
说明数据源限制的方法:比如通过getMaxConnections()方法可以得到查询引擎支持的最大连接数;
说明数据源支持哪些SQL对象,他们的属性是什么:比如getTables()、getPrimaryKeys()方法;
说明数据源提供的事务支持:比如通过getDefaultTransactionIsolation()方法可以得到查询引擎缺省的事务隔离级别。
建议支持接口如下:
函数 |
功能 |
intgetJDBCMajorVersion() |
获取JDBC主版本号 |
String getDatabaseProductName() |
获取系统名称 |
String getDatabaseProductVersion() |
获取版本号 |
String getDriverName() |
获取驱动名称 |
String getDriverVersion() |
获取驱动版本号 |
String getURL() |
获取引擎URL |
关于各种方法的具体说明请参阅JAVA2 SDK DOCUMENT。
5.2ResultSetMetaData
ResultSetMetaData接口提供的方法用于获取一个ResultSet对象各个列的类型和属性,比如列名、列数据类型、列所属的表、以及列是否允许值为 NULL等等。
下面的例子演示了ResultSetMetaData的创建和使用:
假如有一个表StudentInfo(StuIDINT,StuName VARCHAR(10)),下面的例子可以得到这个表的各个列的类型名称:
String sql = “SELECT StuID, StuName FROMStudentInfo”;
ResultSet rs = stmt.executeQuery(sql);
ResultSetMetaData rsmd = rs.getMetaData();
for(int i = 1; i <= rsmd.getColumnCount(); i++)
{
//依次打印出列的类型名称
StringtypeName = rsmd.getColumnTypeName(i);
System.out.println(typeName);
}
建议支持接口如下:
函数 |
功能 |
intgetColomnCount() |
获取字段个数 |
String getColumnName(int column) |
根据结果集中字段索引获取字段名 |
intgetColumnType(int column) |
获取字段的类型代码 |
String getColumnTypeName(int column) |
获取字段类型的名称 |
关于各种方法的具体说明请参阅JAVA2 SDK DOCUMENT。
第6章 批处理
批处理更新机制允许多个更新操作提交给数据源一次处理。相比于一次次单独执行更新,这样的处理方式可以大大的提高效率和性能。Statement、PreparedStatement对象均可以通过addBatch、executeBatch等方法使用批处理更新方式。
6.1Statement中的批处理
当一个Statement对象创建的时候,它的批处理队列是空的。通过调用addBatch()方法,可以将作为参数的SQL语句加入队列中。特别需要指出的是,遵照JDBC3.0规范,所有加入队列的SQL语句必须是执行后返回结果为更新记录数的语句(即insert,delete, update语句和DDL语句),否则将抛出SQLException异常。
如果不打算提交批更新队列中的SQL语句,需要调用clearBatch方法来清空批处理队列。执行批处理更新使用executeBatch方法即可。需要注意的一点:在使用批处理更新之前必须先禁用AutoCommit模式。
下面是一个例子:
//改变auto-commit模式
conn.setAutoCommit(false);
Statementstmt = conn.createStatement();
//设置SQL语句
stmt.addBatch("INSERTINTO employee VALUES (1024, ‘Joe Jones‘)");
stmt.addBatch("INSERTINTO department VALUES (6, ‘Shoe‘)");
stmt.addBatch("INSERTINTO emp_dept VALUES (1024, 6)");
//执行批处理更新
int[]updateCounts = stmt.executeBatch();
conn.commit();
最后说明一点,在批处理队列当中不允许设置保存点(savepoint)。如果要设置,必须在第一条SQL语句被添加到批处理队列中之前。
6.2PreparedStatement中的批处理
在PreparedStatement对象中使用批处理更新机制,是指先对SQL语句执行查询优化,然后在批处理队列中置入多组输入参数,而后提交数据源一次处理。下面是一个例子:
//改变auto-commit模式
conn.setAutoCommit(false);
Stringsql = “INSERT INTO TEMP(ID,VALUE) VALUES(?,?)”;
//先做查询优化
PreparedStatementpstmt = conn.prepareStatement("sql”);
//设置参数值
pstmt.setInt(1,200);
pstmt.setString(2,"Tom Kaufmann");
pstmt.addBatch();
//设置参数值
pstmt.setInt(1,300);
pstmt.setString(2,"Mike Barnes");
pstmt.addBatch();
//执行,取得更新记录
int[]updateCounts = pstmt.executeBatch();
conn.commit();
6.3批处理中的异常处理
在批处理执行过程中,如果有一条语句执行出错,执行将不再继续下去,查询引擎JDBC将会抛出BatchUpdateException,该异常是SQLException的子类。在BatchUpdateException中提供了getUpdateCounts()方法,该方法的返回值是一个int数组。同前面executeBatch()方法一样,该返回数组是一个记录的更新数,数组中的每个值,都是相应SQL语句在查询引擎中更新的记录数。不过getUpdateCounts()返回的数组长度,为正确执行的SQL语句数,而不是批处理中所有的SQL语句数。因此,getUpdateCounts()中包含的记录更新数,将只包含正确执行的SQL语句,而不包含错误执行或没有执行到的SQL语句。
第7章 B参考资料
关于更详细的JDBC Driver 的信息,可以参考JAVA2 SDK DOCUMENT和JDBC3.0规范.可以在http://java.sun.com/products/jdbc/index.html获得相关文档。
JDBC规范(转)