posts - 20,  comments - 7,  trackbacks - 0

JDBC 提供三种类型的语句对象: Statement PreparedStatement CallableStatement

其中 PreparedStatement Statement 的子类, CallableStatement PreparedStatement 的子类。每一种语句对象用来运行特定类型的 SQL 语句。

Statement 对象用来运行简单类型的 SQL 语句,语句中无需指定参数。

PreparedStatement 对象用来运行包含(或不包含) IN 类型参数的预编译 SQL 语句。

CallableStatement 对象用来调用数据库存储过程。

 

 

Statement

1. 概述

Statement 对象用于将 SQL 语句发送到数据库服务器。

 

2. 创建 Statement 对象

建立连接后, Statement 对象用 Connection 对象的 createStatement 方法创建,以下代码创建 Statement 对象:

Connection con = DriverManager.getConnection(url, SYSDBA, SYSDBA);

Statement stmt = con.createStatement();

 

3. 使用 Statement 对象执行语句

Statement 接口提供了三种执行 SQL 语句的方法: executeQuery executeUpdate execute

 

方法 executeQuery 用于产生单个结果集的语句,例如 SELECT 语句。

 

方法 executeUpdate 用于执行 INSERT UPDATE DELETE 语句以及 SQL DDL 语句,如 CREATE TABLE DROP TABLE INSERT UPDATE DELETE 语句的效果是修改表中零行或多行中的一列或多列。 executeUpdate 的返回值是一个整数,表示受影响的行数。对于 CREATE TABLE DROP TABLE DDL 语句, executeUpdate 的返回值总为零。

 

方法 execute 用于执行返回多个结果集、多个更新元组数或二者组合的语句。

 

执行语句的三种方法都将关闭所调用的 Statement 对象的当前打开结果集(如果存在)。这意味着在重新执行 Statement 对象之前,需要完成对当前 ResultSet 对象的处理。

 

4. 关闭 Statement 对象

Statement 对象可由 Java 垃圾收集程序自动关闭。但作为一种好的编程风格,应在不需要 Statement 对象时显式地关闭它们。这将立即释放数据库服务器资源,有助于避免潜在的内存问题。

 

 

 

PreparedStatement

1. 概述

PreparedStatement 继承 Statement ,并与之在两方面有所不同:

PreparedStatement 对象包含已编译的 SQL 语句,语句已经 准备好

包含于 PreparedStatement 对象中的 SQL 语句可具有一个或多个 IN 参数。 IN 参数的值在 SQL 语句创建时未被指定。相反,该语句为每个 IN 参数保留一个问号( )作为占位符。每个问号所对应的值必须在该语句执行之前,通过适当的 setXXX 方法来提供。

由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement 对象。因此,需要多次重复执行的 SQL 语句经常创建为 PreparedStatement 对象,以提高效率。

 

作为 Statement 的子类, PreparedStatement 继承了 Statement 的所有功能。另外它还添加了一整套方法,用于设置发送给数据库以取代 IN 参数占位符的值。同时,三种方法 execute executeQuery executeUpdate 能执行设置好参数的语句对象。

 

2. 创建 PreparedStatement 对象

以下的代码段(其中 con Connection 对象)创建一个 PreparedStatement 对象:

PreparedStatement pstmt = con.prepareStatement( UPDATE 厂商登记 SET 厂商名 = ? WHERE 厂商编号 = ?);

对象 pstmt 包含语句 UPDATE 厂商登记 SET 厂商名 = ? WHERE 厂商编号 = ? ,该语句带两个 IN 参数占位符,它已发送给数据库,并由服务器为其执行作好了准备。

 

3. 传递 IN 参数

在执行 PreparedStatement 对象之前,必须设置每个 ? 参数的值。这可通过调用 setXXX 方法来完成,其中 XXX 是与该参数相应的类型。例如,如果参数具有 Java 类型 String ,则使用的方法就是 setString 。对于不同类型的参数,一般都会有一个推荐的设置方法和多个可行的设置方法。 setXXX 方法的第一个参数是要设置的参数的序号(从 1 算起),第二个参数是设置给该参数的值。譬如,以下代码将第一个参数设为 中华电视机厂 ,第二个参数设为 “B0A01”

pstmt.setString(1, 中华电视机厂 );

pstmt.setString(2, B0A01);

每当设置了给定语句的参数值,就可执行该语句。设置一组新的参数值之前,应先调用 clearParameters 方法清除原先设置的参数值。

 

4. 使用 setObject 方法 : 可显式地将输入参数转换为特定的 JDBC 类型。

该方法可以接受三个参数,其中第三个参数用来指定目标 JDBC 类型。将 Java Object 发送给数据库之前,驱动程序将把它转换为指定的 JDBC 类型。

如果没有指定 JDBC 类型,驱动程序就会将 Java Object 映射到其缺省的 JDBC 类型,然后将它发送到数据库。这与常规的 setXXX 方法类似。在这两种情况下,驱动程序在将值发送到数据库之前,会将该值的 Java 类型映射为适当的 JDBC 类型。

二者的差别在于 setXXX 方法使用从 Java 类型到 JDBC 类型的标准映射,而 setObject 方法使用从 Java Object 类型到 JDBC 类型的映射。

 

方法 setObject 允许接受所有 Java 对象,这使应用程序更为通用,并可在运行时接受参数的输入。这样,如果用户在编辑应用程序时不能确定输入类型,可以通过使用 setObject ,对应用程序赋予可接受的 Java 对象,然后由 JDBC 驱动程序自动将其转换成数据库所需的 JDBC 类型。但如果用户已经清楚输入类型,使用相应的 setXXX 方法是值得推荐的,可以提高效率。

 

5. JDBC NULL 作为 IN 参数发送

setNull 方法允许程序员将 JDBC NULL 值作为 IN 参数发送给数据库。在这种情况下,可以把参数的目标 JDBC 类型指定为任意值,同时参数的目标精度也不再起作用。

 

6. 发送大的 IN 参数

setBytes setString 方法能够发送无限量的数据。但是,内存要足够容纳相关数据。有时程序员更喜欢用较小的块传递大型的数据,这可通过将 IN 参数设置为 Java 输入流来完成。当语句执行时, JDBC 驱动程序将重复调用该输入流,读取其内容并将它们当作实际参数数据传输。

JDBC 提供了四种将 IN 参数设置为输入流的方法: setBinaryStream 用于字节流, setAsciiStream 用于 ASCII 字符流, setUnicodeStream 用于 Unicode 字符流,从 JDK1.2 起,输入字符流的新方法为 setCharacterStream ,而 setAsciiStream setUnicodeStream 已经很少用。

 

7. 获得参数元数据

JDBC 3.0 实现了 getParameterMetaData() 方法,通过这个方法可以获得有关 IN 参数的各种属性信息,比如类型、精度、刻度等信息,类似于结果集元数据的内容。通过这些信息,用户可以更准确地设置 IN 参数的值。 `

在下面的代码中涉及到了这种方法:

PreparedStatement pstmt = conn.prepareStatement(SELECT * FROM BOOKLIST “ + “WHERE ISBN = ? );

...

// 获得参数元数据对象

ParameterMetaData pmd = pstmt.getParameterMetaData();

// 获得参数的个数

int paramCount = pstmt.getParameterCount();

// 获得第一参数的类型

int colType = pmd.getParameterType(1);

8. 自定义方法列表

为了实现对达梦数据库所提供的时间间隔类型和带纳秒的时间类型的支持,在实现 PreparedStatement 接口的过程中,增加了一些自定义的扩展方法。用户将获得的 PreparedStatement 对象反溯成 DmdbPreparedStatment 类型就可以访问这些方法。

 

 

 

CallableStatement

1. 概述

CallableStatement 用来运行 SQL 存储过程。存储过程是数据库中已经存在的 SQL 语句,它通过名字调用。

CallableStatement PreparedStatement 的子类。 CallableStatement 中定义的方法用于处理 OUT 参数或 INOUT 参数的输出部分:注册 OUT 参数的 JDBC 类型(一般 SQL 类型)、从这些参数中检索结果,或者检查所返回的值是否为 JDBC NULL

 

2. 创建 CallableStatement 对象

CallableStatement 对象是用 Connection.prepareCall 创建的。

以下代码创建 CallableStatement 对象,其中含有对存储过程 p1 的调用, con 为连接对象:

CallableStatement cstmt = con.prepareCall(call p1(?, ?));

其中 ? 占位符为 IN OUT 还是 INOUT 参数,取决于存储过程 p1

 

3. IN OUT 参数

IN 参数传给 CallableStatement 对象是通过 setXXX 方法完成的。该方法继承自 PreparedStatement 。所传入参数的类型决定了所用的 setXXX 方法(例如,用 setString 来传入 String 值等)。

如果存储过程返回 OUT 参数,则在执行 CallableStatement 对象之前必须先注册每个 OUT 参数的 JDBC 类型,有的参数还要同时提供刻度。注册 JDBC 类型是用 registerOutParameter 方法来完成的。语句执行完后, CallableStatement getXXX 方法将取回参数值。其中 XXX 是为各参数所注册的 JDBC 类型所对应的 Java 类型。换言之, registerOutParameter 使用的是 JDBC 类型(因此它与数据库返回的 JDBC 类型匹配),而 getXXX 将之转换为 Java 类型。

设存储过程 p1 的定义如下:

CREATE OR REPLACE PROCEDURE p1( a1 IN CHAR(5), a2 OUT CHAR(20)) AS

DECLARE CUR1 CURSOR FOR

SELECT 厂商名

FROM 厂商登记

WHERE 厂商编号 = a1;

BEGIN

OPEN CUR1;

FETCH CUR1 INTO a2;

END;

以下代码先注册 OUT 参数,执行由 cstmt 所调用的存储过程,然后检索通过 OUT 参数返回的值。方法 getString OUT 参数中取出字符串:

CallableStatement cstmt = con.prepareCall(call p1(?, ?));

cstmt.setString(1, B0A05);

cstmt.registerOutParameter(2, java.sql.Types.VARCHAR);

cstmt.executeUpdate();

String x = cstmt.getString(2);

 

4. INOUT 参数

如果参数为既接受输入又接受输出的参数类型( INOUT 参数),那么除了调用 registerOutParameter 方法外,还要调用对应的 setXXX 方法(继承自 PreparedStatement )。 setXXX 方法将参数值设置为输入参数,而 registerOutParameter 方法将它的 JDBC 类型注册为输出参数。 setXXX 方法提供一个 Java 值,驱动程序先把这个值转换为 JDBC 值,然后将它送到数据库服务器。

IN 值的 JDBC 类型和提供给 registerOutParameter 方法的 JDBC 类型应该相同。如果要检索输出值,就要用对应的 getXXX 方法。

设有一个存储过程 p2 的定义如下:

CREATE OR REPLACE PROCEDURE p2(a1  INOUT  CHAR(20)) AS

DECLARE CUR1 CURSOR FOR

SELECT 厂商名

FROM 厂商登记

WHERE 厂商编号 = a1;

BEGIN

OPEN CUR1;

FETCH CUR1 INTO a1;

END;

以下代码中,方法 setString 把参数设为 “B0A05” 。然后, registerOutParameter 将该参数注册为 JDBC VARCHAR 。执行完该存储过程后,将返回一个新的 JDBC VARCHAR 值。方法 getString 将把这个新值作为 Java String 类型返回。

CallableStatement cstmt = con.prepareCall(call p2(?));

cstmt.setString(1, B0A05);

cstmt.registerOutParameter(1, java.sql.Types.VARCHAR);

cstmt.executeUpdate();

String x = cstmt.getString(1);

 

5. 利用参数名进行操作

在通常的情况下一般采用参数索引来进行赋值。 JDBC3.0 规范要求可以利用参数名来对参数进行赋值, DM4 JDBC 3.0 驱动程序实现了这一点。如果某个存储过程的一些参数有默认值,这时候采用参数名进行赋值就非常有用,用户可以只对那些没有默认值的参数进行赋值。参数名可以通过调用 DatabaseMetaData.getProcedureColumns() 来获得。

下面的代码中,存储过程 p2 为上面那个存储过程 p2 。利用参数名进行操作:

CallableStatement cstmt = con.prepareCall({CALL p2 (?)});

cstmt.setString(a1, B0A05);

cstmt.registerOutParameter(a1, java.sql.Types.VARCHAR);

cstmt.executeUpdate();

String x = cstmt.getString(a1);

而且,在读取参数的值和进行参数注册的时候, setXXX getXXX registerOutParameter 也都可以采用参数名来进行操作。通过调用 DatabaseMetaData.supportsNamedParameters() 方法就可以确定 JDBC 驱动程序是否支持利用参数名来进行操作。

注意:在执行同一条语句的过程中,不允许交叉使用参数索引和参数名来进行操作,否则会抛出异常。

 

6. 自定义方法列表

为了实现对达梦数据库所提供的时间间隔类型和带纳秒的时间类型的支持,在实现 CallableStatement 接口的过程中,增加了一些自定义的扩展方法。用户将获得的 CallableStatement 对象反溯成 DmdbCallableStatment 类型就可以访问这些方法。这些方法所涉及到的扩展类请参看 1.2.16 扩展类这一节。

1.2.3 自定义方法列表

方法名 功能说明

getINTERVALYM(int) 获取指定列的 DmdbIntervalYM 类型值。

getINTERVALYM(String) 获取指定列的 DmdbIntervalYM 类型值。

getINTERVALDT(int) 获取指定列的 DmdbIntervalDT 类型值。

getINTERVALDT(String) 获取指定列的 DmdbIntervalDT 类型值。

getTIME(int) 获取指定列的 DmdbTime 类型值。

getTIME(String) 获取指定列的 DmdbTime 类型值。

setTIME(String, DmdbTime) 根据参数名来设置 DmdbTime 类型值。

setINTERVALDT(String, DmdbIntervalDT) 根据参数名来设置 DmdbIntervalDT 类型值。

setINTERVALYM(String, DmdbIntervalYM) 根据参数名来设置 DmdbIntervalYM 类型值。

 

 

 

ResultSet

 

1. 概述

ResultSet 提供执行 SQL 语句后从数据库返回结果中获取数据的方法。执行 SQL 语句后数据库返回结果被 JDBC 处理成结果集对象,可以用 ResultSet 对象的 next 方法以行为单位进行浏览,用 getXXX 方法取出当前行的某一列的值。

通过 Statement PreparedStatement CallableStatement 三种不同类型的语句进行查询都可以返回 ResultSet 类型的对象。

 

2. 行和光标

ResultSet 维护指向其当前数据行的逻辑光标。每调用一次 next 方法,光标向下移动一行。最初它位于第一行之前,因此第一次调用 next 将把光标置于第一行上,使它成为当前行。随着每次调用 next 导致光标向下移动一行,按照从上至下的次序获取 ResultSet 行。

ResultSet 对象或对应的 Statement 对象关闭之前,光标一直保持有效。

 

3.

方法 getXXX 提供了获取当前行中某列值的途径。在每一行内,可按任何次序获取列值。

列名或列号可用于标识要从中获取数据的列。例如,如果 ResultSet 对象 rs 的第二列名为 “title” ,则下列两种方法都可以获取存储在该列中的值:

String s = rs.getString(title);

String s = rs.getString(2);

注意列是从左至右编号的,并且从 1 开始。

 

关于 ResultSet 中列的信息,可通过调用方法 ResultSet.getMetaData 得到。返回的 ResultSetMetaData 对象将给出其 ResultSet 对象各列的名称、类型和其他属性。

 

4. 采用流方式获取列值

为了获取大数据量的列, JDBC 驱动程序提供了四个获取流的方法:

getBinaryStream 返回只提供数据库原字节而不进行任何转换的流。

getAsciiStream 返回提供单字节 ASCII 字符的流。

getUnicodeStream 返回提供双字节 Unicode 字符的流。

getCharacterStream 返回提供双字节 Unicode 字符的 java.io.Reader 流。

在这四个函数中, JDBC 规范不推荐使用 getCharacterStream 方法,其功能可以用 getUnicodeStream 代替。

 

5. NULL 结果值

要确定给定结果值是否是 JDBC NULL ,必须先读取该列,然后使用 ResultSet 对象的 wasNull 方法检查该次读取是否返回 JDBC NULL

当使用 ResultSet 对象的 getXXX 方法读取 JDBC NULL 时,将返回下列值之一:

Java null 值:对于返回 Java 对象的 getXXX 方法(如 getString getBigDecimal getBytes getDate getTime getTimestamp getAsciiStream getUnicodeStream getBinaryStream getObject 等)。

零值:对于 getByte getShort getInt getLong getFloat getDouble

false 值:对于 getBoolean

 

6. 结果集增强特性

JDBC 驱动程序中提供了符合 JDBC 2.0 标准的结果集增强特性:可滚动、可更新结果集。及 JDBC3.0 标准的可持有性。

(1) 结果集的可滚动性

通过执行语句而创建的结果集不仅支持向前(从第一行到最后一行)浏览内容,而且还支持向后(从最后一行到第一行)浏览内容的能力。支持这种能力的结果集被称为可滚动的结果集。可滚动的结果集同时也支持相对定位和绝对定位。绝对定位指的是通过指定在结果集中的绝对位置而直接移动到某行的能力,而相对定位则指的是通过指定相对于当前行的位置来移动到某行的能力。

 

 JDBC 驱动程序中支持只向前滚结果集 (ResultSet.TYPE_FORWARD_ONLY) 和滚动不敏感结果集 (ResultSet.TYPE_SCROLL_INSENSITIVE) 两种结果集类型,不支持滚动敏感结果集 (ResultSet.TYPE_SCROLL_SENSITIVE) 。当结果集为滚动不敏感结果集时,它提供所含基本数据的静态视图,即结果集中各行的成员顺序、列值通常都是固定的。

 

(2) 结果集的可更新性

DM4 JDBC 驱动程序中提供了两种结果集并发类型:只读结果集 (ResultSet.CONCUR_READ_ONLY) 和可更新结果集 (ResultSet.CONCUR_UPDATABLE) 。采用只读并发类型的结果集不允许对其内容进行更新。可更新的结果集支持结果集的更新操作。

 

(3) 结果集的可持有性

JDBC 3.0 提供了两种结果集可持有类型:提交关闭结果集 (ResultSet.CLOSE_CURSORS_AT_COMMIT) 和跨结果集提交 (ResultSet.HOLD_CURSORS_OVER_COMMIT) 。采用提交关闭结果集类型的结果集在事务提交之后被关闭,而跨结果集提交类型的结果集在事务提交之后仍能保持打开状态。

通过 DatabaseMetaData.supportsHoldability() 方法可以确定驱动程序是否支持结果集的可持有性。目前 DM4 支持这两种类型。

 

(4) 性能优化

JDBC 驱动程序的结果集对象中提供了方法 setFetchDirection setFetchSize 来设置缺省检索结果集的方向和缺省一次从数据库获取的记录条数。它们的含义与用法和语句对象中的同名函数是相同的。

 

7. 更新大对象数据

JDBC 2.0 驱动程序就支持可更新的结果集,但是对 LOB 对象只能读取,而不能更新,这也是 JDBC 2.0 标准所规定的。而 JDBC 3.0 规范规定用户可以对 LOB 对象进行更新, DM4 JDBC 3.0 驱动程序中实现了这一点:

Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,

ResultSet.CONCUR_UPDATABLE);

ResultSet rs = stmt.executeQuery(select comment from booklist +

where isbn = 140185852);

rs.next();

Clob commentClob = new Clob(...)

rs.updateClob(author, commentClob);  // commentClob is a Clob Object

rs.updateRow();

 

 

 

 ResultSetMetaData

 

1. 概述

ResultSetMetaData 提供许多方法,用于读取 ResultSet 对象返回数据的元信息。包括:列名、列数据类型、列所属的表、以及列是否允许为 NULL 值等,通过这些方法可以确定结果集中列的一些信息。

2. 创建结果集元数据对象

结果集元数据是用来描述结果集的特征,所以,需要首先执行查询获得结果集,才能创建结果集元数据对象。

3. 创建 ResultSetMetaData 对象如下例所示:

假如有一个表 TESTTABLE(no int,name varchar(10)) ,利用下面的代码就可以知道这个表的各个列的类型:

ResultSet rs = stmt.executeQuery(SELECT * FROM TESTTABLE);

ResultSetMetaData rsmd = rs.getMetaData();

for(int i = 1; i <= rsmd.getColumnCount(); i ++)

{

   String typeName = rsmd.getColumnTypeName(i);

   System.out.println( + i + 列的类型为: + typeName);

}

 

DatabaseMetaData

1. 概述

DatabaseMetaData 提供了许多方法,用于获取数据库的元数据信息。包括:描述数据库特征的信息 ( 如是否支持多个结果集 ) 、目录信息、模式信息、表信息、表权限信息、表列信息、存储过程信息等。 DatabaseMetaData 有部分方法以 ResultSet 对象的形式返回结果,可以用 ResultSet 对象的 getXXX() 方法获取所需的数据。

 

2. 创建数据库元数据对象

数据库元数据对象由连接对象创建。以下代码创建 DatabaseMetaData 对象(其中 con 为连接对象):

DatabaseMetaData dbmd = con.getMetaData();

利用该数据库元数据对象就可以获得一些有关数据库和 JDBC 驱动程序的信息:

String databaseName = dbmd.getDatabaseProductName();  // 数据库产品的名称

int majorVersion = dbmd.getJDBCMajorVersion();  // JDBC 驱动程序的主版本号

String []types ={TABLE};

ResultSet tablesInfor = dbmd.getTables(null,  null,  “*TE%”,  types);

 

数据类型访问

1 .概述

对数据的访问主要是

(1) 通过 PreparedStatement 对象、 CallableStatement 对象的 setXXX 方法以及 ResultSet 对象的 updateXXX() 方法进行设置 ;

 (2) 通过 CallableStatement 对象、 ResultSet 对象的 getXXX() 方法来进行检索。

 

2 .各个类型能采用的 setXXX 方法或 updateXXX 方法

请参看 SUN 公司的 JDBC 3.0 specification 文档第 186 页的 TABLE-6 。一般地,只要把里面的 getXXX 改为 setXXX updateXXX 即可。

 

3 .各个类型能采用的 getXXX 方法

请参看 SUN 公司的 JDBC 3.0 specification 文档第 186 页的 TABLE-6

 

 

 ParameterMetaData

 

1 .概述

参数元数据是 JDBC 3.0 标准新引入的接口,它主要是对 PreparedStatement CallableStatement 对象中的 ? 参数进行描述,例如参数的个数、参数的类型、参数的精度等信息,类似于 ResultSetMetaData 接口。通过引入这个接口,就可以对参数进行较为详细、准确的操作。

2 .创建参数元数据对象

通过调用 PreparedStatement CallableStatement 对象的 getParameterMetaData() 方法就可以获得该预编译对象的 ParameterMetaData 对象:

ParameterMetaData pmd = pstmt.getParameterMetaData();

然后就可以利用这个对象来获得一些有关参数描述的信息:

// 获取参数个数

int paraCount = pmd.getParameterCount();

for(int i = 1; i <= paraCount; i ++) {

// 获取参数类型

System.out.println(The Type of Parameter(+i+) is + ptmt.getParameterType(i));

// 获取参数类型名

System.out.println(The Type Name of Parameter(+i+) is

+ ptmt.getParameterTypeName(i));

// 获取参数精度

System.out.println(The Precision of Parameter(+i+) is + ptmt.getPrecision(i));

// 获取参数是否为空

System.out.println(Parameter(+i+) is nullable? + ptmt.isNullable (i));

}

 

 

  大对象

 

1 .概述

JDBC 标准为了增强对大数据对象的操作,在 JDBC 3.0 标准中增加了 java.sql.Blob java.sql.Clob 这两个接口。这两个接口定义了许多操作大对象的方法,通过这些方法就可以对大对象的内容进行操作。

 

2 .产生 Lob 对象

ResultSet CallableStatement 对象中调用 getBlob() getClob() 方法就可以获得 Blob 对象和 Clob 对象:

Blob blob = rs.getBlob(1);

Clob clob = rs.getClob(2);

 

3 .设置 Lob 对象

Lob 对象可以像普通数据类型一样作为参数来进行参数赋值,在操作 PreparedStatement CallableStatement ResultSet 对象时使用:

PreparedStatement pstmt = conn.prepareStatement(INSERT INTO bio (image, text) “ +

“VALUES (?, ?));

//authorImage is a Blob Object

pstmt.setBlob(1, authorImage);

//authorBio is a Clob Object

pstmt.setClob(2, authorBio);

在一个可更新的结果集中,也可以利用 updateBlob(int,Blob) updateClob(int,Clob) 来更新当前行。

 

4 .改变 Lob 对象的内容

Lob 接口提供了方法让用户可以对 Lob 对象的内容进行任意修改:  

byte[] val = {0,1,2,3,4};

 

Blob data = rs.getBlob(DATA);

int numWritten = data.setBytes(1, val); // 在指定的位置插入数据

PreparedStatement ps = conn.prepareStatement(UPDATE datatab SET data = ?);

ps.setBlob(DATA, data);

ps.executeUpdate();

 

 

 

 Savepoint

 

1 .概述

为了增加对事务的控制, JDBC 规范 3.0 增加了 Savepoint 这个接口。它代表一个逻辑事务点。在非自动提交模式下,一个事务中可以设置多个 Savepoint 。这样在回滚时,可以回滚到指定的 Savepoint ,从事务开始到该 Savepoint 之间的操作依然保留着。这就提高了事务处理的粒度,更好地操纵数据。

Savepoint 分为命名的和未命名的两种。未命名的用系统分配的 ID 作为标识。同时可以通过 DatabaseMetaData.supportsSavepoint() 来判断 JDBC 驱动程序是否支持 Savepoint

 

2 .操作 Savepoint

Savepoint 的操作位于 Conncetion 接口:

Statement stmt = conn.createStatement();

int rows = stmt.executeUpdate(insert into tab1(col) values(' first') ); // 插入第一条数据

Savepoint svpt1 = conn.setSavepoint(SAVEPOINT_1); // 设置一个 Savepoint

rows = stmt.executeUpdate(intert into tab1(col) values('second') ); // 插入第二条数据

……

conn.rollback(svpt1); // 回滚到指定的 Savepoint

……

conn.commit(); // 提交事务 , 真正在数据库中仅插入了第一条数据

这样,数据库中仅增加了第一次插入的那条记录。注意:在使用 Savepoint 之前,一定要把当前连接设置为非自动提交模式。

在事务提交之后,先前事务中的所有 Savepoint 都自动取消。如果有两个 Savepoint ,当事务回滚到前面的那个 Savepoint 时,后面的这个 Savepoint 也自动取消。

 

autoGenerated Key

 

在很多数据库中,插入一条新的记录时数据库会为新增的记录自动产生一个唯一的标识。 JDBC3.0 规范中的 Statement 新增了一个方法: getGeneratedKeys ,利用这个方法就可以检索出系统自动为插入的新行所产生的关键字。可以传递一个 Statement.RETURN_GENERATED_KEYS 标识给 Statement 对象的 execute executeUpdate() 的方法或者 PreparedStatement 对象的一些方法,这样在执行完这些方法之后就可以检索新产生的关键字。

Statement stmt  = conn.createStatement();

int rows = stmt.executeUpdate(insert into orders(isbn,customerid) values(1953, 'billg') ,

Statement.RETURN_GENERATED_KEYS);

ResultSet rs = stmt.getGeneratedKeys();

boolean b = rs.next();

if (b)

{

// 检索新产生的关键字的值

……

}

为了检索方便,用户也可以为自动产生的关键字指定列名或者索引:

String[] keyColumn = {order_id};

… …

Statement stmt = conn.createStatement();

int rows = stmt.executeUpdate(insert into orders (isbn,customerid) values(9664, 'Billg') ,keyColumn);

ResultSet rs = stmt.getGeneratedKeys();

while(rs.next())

{

// 检索新产生的关键字的值

byte[] bs = rs.getBytes(order_id);

}

……

JDBC 驱动程序是否支持自动产生的关键字,可以通过 DataBaseMetaData.supportsGetGeneratedKeys 来判断。

 

 

  数据源 DataSource

 

数据源是 JDBC 2.0 规范作为扩展包引入的,在 JDBC 3.0 规范中成为核心 API 。数据源不仅能够从功能上完全取代利用 DriverManager 建立连接的方式,而且具有以下几点优势:

(1) 增强了代码的可移植性;

(2) 方便了代码的维护;

(3) 利用连接池来提高系统的性能。

 

JDBC 驱动程序提供了对数据源的支持,实现了 javax.sql.DataSource 接口和 java.sql.ConnectionPoolDataSource 接口。用户通过 javax.sql.DataSource 接口来建立连接。

 

使用数据源来建立连接时,

首先要向 JNDI 注册一个数据源。在建立连接的时候,首先通过 JNDI 来获得要使用的数据源:

DataSource ds = (DataSource) ctx.lookup(datasourceName)

然后使用这个数据源来建立连接对象:

Connection con = ds.getConnection()

该连接同通过 DriverManager 所建立的连接是一样的。

 

实现 javax.sql.ConnectionPoolDataSource 接口是为了提高系统的性能。通过设置一个连接缓冲区,在其中保持数目较小的物理连接的方式,这个连接缓冲区由大量的并行用户共享和重新使用,从而避免在每次需要时建立一个新的物理连接,以及当其被释放时关闭该连接的昂贵操作。该连接池是 JDBC 提供系统性能的一种措施,是在 JDBC 内部实现的,能够为用户提供透明的高速缓冲连接访问。用户利用数据源来建立连接的应用不需为此做出任何代码上的变动。

posted on 2006-07-25 08:49 Lizzie 阅读(2606) 评论(0)  编辑  收藏 所属分类: 专业积木

只有注册用户登录后才能发表评论。


网站导航:
 

<2006年7月>
2526272829301
2345678
9101112131415
16171819202122
23242526272829
303112345

常用链接

留言簿(1)

随笔分类

随笔档案

文章分类

搜索

  •  

最新评论

阅读排行榜

评论排行榜