6.1 为了避免歧义,我们将在讨论规约时这些术语:
- JDBC driver implementation
JDBC技术驱动的驱动程序及其底层数据源。驱动程序可以为基础数据源未实现的特性提供支持。它还可以提供标准语法/语义和由数据源实现的本机API之间的映射 - Relevant specifications
本文档,API规范,以及相关的SQL规范。如果在以上文档中描述了一个特性,那么这也是优先顺序。对JDBC API,它是SQL92加SQL相关的部分:2003,X/Open SQL CLI - Supported feature
JDBC实现支持相关规范中定义的该特性的标准语法和语义的特性。 - Extension
没有任何相关规范所涵盖的特性或覆盖的特性的非标准实现。 - Fully implemented
用于实现所有方法以支持相关规范中定义的语义的接口的术语。没有一个方法可以抛出异常,因为它们没有实现 - Must implement
虽然接口上的某些方法被认为是可选的,但接口是必须实现的。方法不执行必须抛出一个sqlfeaturenotsupportedexception表明相应的功能不支持
6.2 指导规范和要求
以下的准则是 JDBC API 规范要求实现者遵守的基本准则
- JDBC API 的实现者必须支持 Entry Level SQL92 标准,以及 Drop Table 命令。对 Entry Level SQL92 标准的支持是实现 JDBC API 的最小要求,对于 SQL99 和 SQL2003 特性的实现,必须遵照 SQL99 和 SQL2003 的规范
- JDBC 驱动必须支持转义语法,转义语法在 第十三章 中有详细解释。
- JDBC 驱动必须支持事务,参考 第十章。
- 如果 DatabaseMetaData 的某个方法指明某个特性的可用的,那么驱动必须根据这个特性的相关规范中规定的标准语法实现这个特性,如果该特性需要使用到数据源的原生 API 或者是 SQL 方言,那么由驱动负责实现从标准 SQL 语法到原生 API 或者 SQL 方言的映射关系。如果支持了某个特性,那么 DatabaseMetaData 中与这个特性相关的方法也必须提供实现。比如说,如果一个驱动实现了 RowSet 接口,那么它也应该实现 RowSetMetaData 接口。
- 驱动必须提供对底层数据源特性的访问方式,包括扩展了 JDBC API 的特性。这么规定的目的是能让使用了 JDBC API 的应用程度能像数据源的原生程序一样,访问与数据源有关的特性。
- 如果一个 JDBC 驱动不支持,或者部分支持某个可选的数据库特性,那么 DatabaseMetaData 的方法必须指明这个特性还没受到支持,任何还没实现或者还没支持的特性,如果应用程序使用到了,那么应该给应用程序抛一个 SQLFeatureNotSupportedException
注意 —— 根据 SQL92 的规定, JDBC 驱动需要支持 DROP TABLE 命令,不过,是否实现 CASCADE 和 RESTRICT,则是可选的,不是必须的。此外, 当数据源里需要 drop 的表定义了视图、完整性约束时,如何实现 DROP TABLE 来处理这种情况,则每个驱动允许有不同的做法。
6.3 JDBC 4.2 API 要求驱动程序遵守的准则
符合JDBC规范的驱动程序必须执行以下操作:
- 遵守前一章的指导规范和要求
- 支持自动加载所有实现了 java.sql.Driver 的驱动类
- ResultSet 支持 TYPE_FORWARD_ONLY 类型
- ResultSet 支持 CONCUR_READ_ONLY 并发级别
- 支持批量更新
- 完全实现以下接口
1,java.sql.DatabaseMetaData,
2,java.sql.ParameterMetaData
3,java.sql.ResultSetMetaData,
4,java.sql.Wrapper - 必须实现 DataSource 接口,但以下方法是可选的
1,getParentLogger - 除了下列可选方法外,它必须实现 Driver 接口
1,getParentLogger - 必须实现 Connection 接口,但以下方法是可选的
1,createArrayOf
2,createBlob,
3,createClob
4,createNClob,
5,createSQLXML
6,createStruct,
7,getNetworkTimeout
8,getTypeMap,
9,setTypeMap
9,prepareStatement(String sql, Statement.RETURN_GENERATED_KEYS),
10,prepareStatement(String sql, int[] columnIndexes)
11,prepareStatement(String sql, String[] columnNames),
12,setSavePoint
13,rollback(java.sql.SavePoint savepoint),
14,releaseSavePoint
15,setNetworkTimeout - 必须实现 Statement 接口,但以下方法是可选的
1,cancel,
2,execute(String sql, Statement.RETURN_GENERATED_KEYS)
3,execute(String sql, int[] columnIndexes),
4,execute(String sql, String[] columnNames)
5,executeUpdate(String sql, Statement.RETURN_GENERATED_KEYS)
6,executeUpdate(String sql, int[] columnIndexes)
7,executeUpdate(String sql, String[] columnNames),
8,getGeneratedKeys
9,getMoreResults(Statement.KEEP_CURRENT_RESULT),除非
10,DatabasemetaData.supportsMultipleOpenResults() 返回 true,否则是可选的。
11,getMoreResults(Statement.CLOSE_ALL_RESULTS) 除非,
12,DatabasemetaData.supportsMultipleOpenResults() 返回 true,否则是可选的。
setCursorName - 必须实现 PreparedStatement 接口,但以下方法是可选的
1,getMetaData,
2,setArray, setBlob, setClob, setNClob, setNCharacterStream, setNString, setRef, setRowId, 3,setSQLXML and setURL,
4,setNull(int parameterIndex,int sqlType, String typeName)
5,setUnicodeStream,
6,setAsciiStream, setBinaryStream, setCharacterStream,
setNCharacterStream - 如果 DatabaseMetaData.supportsStoredProcedures() 返回 true, 那么必须实现 CallableStatement 接口,但以下方法是可选的
1,所有的 setXXX, getXXX 方法,以及所有支持命名参数的 registerOutputParameter 方法,
2,getArray, getBlob, getClob, getNClob, getNCharacterStream, getNString, getRef, getRowId, 3,getSQLXML and getURL,
4,getBigDecimal(int parameterIndex,int scale)
5,getObject(int i, Class<T> type)
6,getObject(String colName, Class<T> type),
7,getObject(int parameterIndex, java.util.Map<java.lang.String,java.lang.Class<?>> map)
8,registerOutputParam(String parameterName,int sqlType, String typeName),
8,setNull(String parameterName,int sqlType, String typeName)
9,setAsciiStream, setBinaryStream, setCharacterStream, setNCharacterStream - 必须实现 RowSet 接口,但以下方法是可选的
1,所有的 updateXXX 方法,
2,absolute
3,afterLast
4,beforeFirst,
5,cancelRowUpdates,
6,deleteRowfirst,
7,getArray, getBlob, getClob, getNClob, getNCharacterStream, getNString, getRef, getRowId, 8,getSQLXML and getURL,
9,getBigDecimal(int i,int scale)
10,getBigDecimal(String colName,int scale),
11,getCursorName
12,getObject(int i, Class<T> type)
13,getObject(String colName, Class<T> type),
14,getObject(int i, Map<String,Class<?>> map)
15,getObject(String colName, Map<String,Class<?>> map)
16,getRow
17,getUnicodeStream
18,insertRow
19,isAfterLast
20,isBeforeFirst
21,isFirst
22,isLast
23,last
24,moveToCurrentRow
25,moveToInsertRow,
26,previous
27,refreshRow,
28,relative
29,rowDeleted
r30,owInserted,
31,rowUpdated
32,updateRow - 如果一个 JDBC 驱动支持 ResultSet 的 CONCUR_UPDATABLE 并发级别,那么必须实现以下方法
1,除了 updateArray, updateBlob, updateClob, updateNClob, updateNCharacterstream,,
updateNString, updateRef, updateRowId, updateSQLXML, updateURL, updateBlob,
updateClob, updateNClob, updateAsciiStream, updateBinaryStream, updateCharacterStream and updateNCharacterstream 之外的所有 updateXXX 方法。
2,cancelRowUpdates
3,deleteRow
4,rowDeleted
5,rowUpdated
6,updateRow - 如果一个JDBC驱动程序支持的type_scroll_sensitive或type_scroll_insensitive 的 ResultSet类型,下面的ResultSet接口方法必须实现
1,absolute
2,afterLast
3,beforeFirst
4,first
5,isAfterLast
6,isBeforeFirst
7,isFirst
8,isLast
9,last
10,previous
11,relative - 如果实现了可选接口,则接口上的所有方法也必须完全实现,有以下例外情况
1,java.sql.SQLInput 和 java.sql.SQLOutput 接口不要求实现 Array, Blob, Clob, NClob, NString, Ref, RowId, SQLXML and URL 这些数据类型
6.4 Java EE 中的 JDBC 规范准则
在 Java EE 环境中使用的 JDBC 驱动,除了必须遵守前文中提到所有规定外,还必须遵守以下规定:
- 驱动必须支持存储过程,DatabaseMetaData 接口的 supportsStoredProcedures 方法必须返回 true,驱动也需要在调用 Statement, PreparedStatement, and CallableStatement 的方法时,支持转义语法,这些方法是:
1, executeUpdate
2, executeQuery
3, execute
对于存储过程的支持,仅仅需要驱动在调用 Statement, PreparedStatement, and CallableStatement 接口的 execute 方法时,要么返回一个更新数量,要么返回一个单一的 ResultSet 对象。这是因为有些数据库不支持调用存储过程后返回多个 ResultSet 对象。
同时也要支持所有的参数类型,包括 IN, OUT, INOUT
- 驱动必须支持下面这些函数的转义语法
ABS
CONCAT
LCASE
LENGTH
LOCATE (two argument version only)
LTRIM
MOD
RTRIM
SQRT
SUBSTRING
UCASE