PreparedStatement
1. 概述
PreparedStatement 继承 Statement,并与之在两方面有所不同:
1) PreparedStatement 对象包含已编译的 SQL 语句,语句已经“准备好”;
2) 包含于 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 person.person SET name = ? WHERE personid = ?");
对象 pstmt 包含语句 "UPDATE person.person SET name = ? WHERE personid = ?",该语
句带两个 IN 参数占位符,它已发送给数据库,并由服务器为其执行作好了准备。
3. 传递 IN 参数
在执行 PreparedStatement 对象之前,必须设置占位符(“?”)的值。这可通过调用 setXXX
方法来完成,其中 XXX 是与该参数相应的类型。例如,如果参数具有 Java 类型 String,则
使用的方法就是 setString。setXXX 方法的第一个参数是要设置的参数的序号(从 1 算起),
第二个参数是设置给该参数的值。譬如,以下代码将第一个参数设为“张三”,第二个参数
设为“18”:
pstmt.setString(1, "张三"); pstmt.setInt(2, 18);
每当设置了给定语句的参数值,就可执行该语句。设置一组新的参数值之前,应先调用
clearParameters 方法清除原先设置的参数值。
4. 使用 setObject
setObject 方法可显式地将输入参数转换为特定的 JDBC 类型。该方法可以接受三个参
数,其中第三个参数用来指定目标 JDBC 类型。将 Java Object 发送给数据库之前,驱动程
序将把它转换为指定的 JDBC 类型。例如,上面的 setXXX 语句就可以改写为:
pstmt.setObject(1, "张三", java.sql.Types.VARCHAR); pstmt.setObject(2, 18, java.sql.Types.INTEGER);
如果没有指定 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. 获得参数元数据
DM JDBC 实现了 getParameterMetaData()方法,通过这个方法可以获得有关 IN 参数的
各种属性信息,比如类型、精度、刻度等信息,类似于结果集元数据的内容。通过这些信息,
用户可以更准确地设置 IN 参数的值。
在下面的代码中涉及到了这种方法:
PreparedStatement pstmt = conn.prepareStatement("SELECT * FROM person.person " + "WHERE personid = ?"); ... //获得参数元数据对象 ParameterMetaData pmd = pstmt.getParameterMetaData(); //获得参数的个数 int paramCount = pmd.getParameterCount(); //获得第一参数的类型 int colType = pmd.getParameterType(1); …
8. 自定义方法列表
为了实现对达梦数据库所提供的时间间隔类型和带纳秒的时间类型的支持,在实现
PreparedStatement 接 口 的 过 程 中 , 增 加 了 一 些 自 定 义 的 扩 展 方 法 。 用 户 将 获 得 的
PreparedStatement 对象反溯成 DmdbPreparedStatment 类型就可以访问这些方法。这些方法所
涉及到的扩展类请参看 4.4 节。
表 4.2 自定义方法列表
方法名 |
功能说明 |
setINTERVALYM |
设置参数为年-月时间间隔类型值 |
setINTERVALDT |
设置参数为日-时时间间隔类型值 |
setTIME |
设置参数为时间类型(带纳秒) |
例如,想要插入一个年月时间间隔类型,代码如下(pstmt 为 PreparedStatement 类型):
DmdbPreparedStatement dmps = (DmdbPreparedStatement)pstmt; DmdbIntervalYM dmiym = new DmdbIntervalYM("interval '20-10' year to month"); dmps.setINTERVALYM(1, dmiym);
另外,DM 中不支持 JDBC 规范中所要求的标准方法 setURL 和 setRef。
评论