2022 年 1 月 5 日更新
本文档提供关于 Oracle JDBC 驱动程序的常见问题解答。请注意,本常见问题解答仅针对特定技术问题,旨在提供各种常见客户问题和所有已知问题的解决方法。更多信息,请参阅 JDBC 参考指南和 Javadoc for JDBC。
以下是 19c 的关键 JDBC 特性。更多信息,请参阅重新认识使用 RDBMS 的 Java 应用的性能和可伸缩性。
最新 Java 标准:支持 JDK17、JDK11 和 JDK8,符合 JDBC 4.3(ojdbc11.jar 和 ojdbc10.jar)和 JDBC 4.2(ojdbc8.jar)— 采用 JDBC 驱动程序和通用连接池(ucp.jar)
当使用 JDBC 驱动程序和/或 UCP 时,Java 开发人员可以访问面向数据库云的 JDBC 页面,查看关于连接云数据库服务的更多信息。
您可以访问 Oracle JDBC 驱动程序页面以及 JDBC 开发人员指南和 JDBC Github 来详细了解 JDBC。
您还可以通过各种书籍来了解 JDBC,我们建议您首先阅读 JDBC API 教程与参考手册(第 3 版) 。
您可以访问 Oracle Java 网站来详细了解 Java。
您还可以通过各种书籍来了解 Java,其中最流行的包括:
请参阅下表,了解 JDBC 驱动程序支持信息。请注意,下表是为方便您查看而提供的汇总信息,我们建议您参阅终身支持政策(第 4 页),了解更多信息及最新更新(如有)。
版本 | GA 日期 | 标准支持终止日期 | 扩展支持终止日期 | 持续支持终止日期 |
---|---|---|---|---|
21c(创新版本) | 2021 年 8 月 | 2024 年 4 月 | 不适用 | 未定义 |
19c(长期发行版本) | 2019 年 4 月 | 2024 年 4 月 | 2027 年 4 月 | 未定义 |
18c | 2018 年 7 月 | 2021 年 6 月 | 不适用 | 未定义 |
12.2 | 2017 年 3 月 | 2020 年 11 月 30 日(面向 12.2.01 版本的有限误差修正期 — 2020 年 12 月 1 日至 2022 年 3 月 31 日) | 不适用 | 未定义 |
EE 12.1 | 2013 年 6 月 | 2018 年 7 月 | 2022 年 7 月 | 未定义 |
请参见下表,了解 JDBC 驱动程序与 Oracle 数据库的互操作性矩阵。为确保充分利用 JDBC 驱动程序的最新功能,我们建议您始终使用版本号等于或高于 Oracle 数据库的 JDBC 驱动程序。
互操作性矩阵 | Database 23.3 | Database 21.x | Database 19.x | Database 18.3 | Database 12.2 和 12.1 |
---|---|---|---|---|---|
JDBC 23.3 | 支持 | 支持 | 支持 | 不支持 | 不支持 |
JDBC 21.x | 支持 | 支持 | 支持 | 曾经支持 | 曾经支持 |
JDBC 19.x | 支持 | 支持 | 支持 | 曾经支持 | 曾经支持 |
JDBC 18.x | 不支持 | 曾经支持 | 曾经支持 | 曾经支持 | 曾经支持 |
JDBC 12.2 和 12.1 | 不支持 | 曾经支持 | 曾经支持 | 曾经支持 | 曾经支持 |
每个新发行 Oracle JDBC 的驱动程序始终兼容最新版本的 JDK。在某些版本中,JDBC 驱动程序支持多个版本的 JDK。请参考下表,基于您的 JDK 版本选择合适的 JDBC 驱动程序。
Oracle 数据库版本 | 特定于 JDK 版本的 JDBC Jar 文件 |
---|---|
23.x | ojdbc11.jar 兼容 JDK11、JDK17 JDK19 和 JDK21 ojdbc8.jar 兼容JDK8 和 JDK11 |
21.x | ojdbc11.jar 兼容 JDK11、JDK17 和 JDK19 ojdbc8.jar 兼容JDK8 和 JDK11 |
19.x | ojdbc10.jar 兼容 JDK11 和 JDK17 ojdbc8.jar 兼容JDK8、JDK11、JDK17 和 JDK19 |
18.x | ojdbc8.jar 兼容 JDK8 和 JDK11 |
12.2 或 12cR2 | ojdbc8.jar 兼容 JDK 8 |
12.1 或 12cR1 | ojdbc7.jar 兼容 JDK 7 和 JDK 8 ojdbc6.jar 兼容 JDK 6 |
11.2 或 11gR2 | ojdbc6.jar 兼容 JDK 6、JDK 7 和 JDK 8 (注意:仅 11.2.0.3 和 11.2.0.4 版本支持 JDK7 和 JDK8) ojdbc5.jar 兼容 JDK 5 |
下表描述了各个版本 Oracle JDBC 的驱动程序及其遵循的 JDBC 规范。
Oracle 数据库版本 | JDBC 规范合规性 |
---|---|
23.x 和 21.x | ojdbc11.jar 遵循 JDBC 4.3 规范 ojdbc8.jar 遵循 JDBC 4.2 规范 |
19.x | ojdbc10.jar 遵循 JDBC 4.3 规范 ojdbc8.jar 遵循 JDBC 4.2 规范 |
18.3 | ojdbc8.jar 遵循 JDBC 4.2 规范 |
12.2 或 12cR2 | ojdbc8.jar 遵循 JDBC 4.2 规范 |
12.1 或 12cR1 | ojdbc7.jar 遵循 JDBC 4.1 规范 ojdbc6.jar 遵循 JDBC 4.0 规范 |
11.2 或 11gR2 | ojdbc6.jar 遵循 JDBC 4.0 标准 ojdbc5.jar 遵循 JDBC 3.0 标准 |
Oracle JDBC 驱动程序仅通过 Oracle JVM(以前称为 Sun JVM)认证。但是,客户一直在将 Oracle JDBC 驱动程序与非 Oracle JVM 结合使用(例如 IBM JVM)。唯一需要注意的是,如果需要 Oracle JDBC 开发团队和 Oracle Support 团队帮助您解决与 Oracle JDBC 驱动程序有关的问题,您必须在 Oracle JVM 上重现相关问题。
Oracle Database 19.x 提供
(a) ojdbc8.jar(使用 JDK8 (JDBC 4.2) 编译,支持 JDK9 和 JDK11)
(b) ojdbc10.jar(使用 JDK10 (JDBC 4.3) 编译,支持 JDK11)。
对于 JDK11,我们建议您优先使用 ojdbc8.jar,因为它支持 JDBC 4.3 的所有特性并进行了一定的扩展。仅当需要在标准版 Java SE 中使用 JDBC 4.3 特性时,我们才推荐您使用 ojdbc10.jar。
示例:
ojdbc8.jar:Connection conn = DriverManager.getConnection(. . .); // conn.beginRequest(); 失败,因为 Java 8 不支持 beginRequest ((OracleConnection)conn).beginRequest(); // 成功,因为 beginRequest 是 Oracle 扩展
Connection conn = DriverManager.getConnection(. . .); conn.beginRequest(); // 成功,因为 Java 10 支持 beginRequest ((OracleConnection)conn).beginRequest(); // 成功,因为 OracleConnection 支持 JDBC 4.3 (Java 10) 且 JDBC 4。3 支持 beginRequest
对于上表所示以外版本的 JDBC,请联系您的支持渠道,确认您的旧版本支持合同是否仍然有效。
请前往 Oracle Technology Network 的 JDBC 下载页面,下载您需要的 JDBC Jar 和其他配套 Jar 文件,例如 orai18n.jar、oraclepki.jar、osdt_core.jar 或 osdt_cert.jar
。
请参阅下表,了解有关 JDBC 驱动程序的更多信息。
Oracle 提供四种类型的 JDBC 驱动程序,分别适用于不同的部署场景。这四种 Oracle JDBC 驱动程序十分相似,但某些特性仅适用于 JDBC OCI 驱动程序,另一些特性则仅适用于 JDBC Thin 驱动程序。
由于使用了本地方法,JDBC OCI 驱动程序只适用于特定平台。对此,Oracle 支持 Solaris、Windows 和许多其他平台。
JDBC OCI 驱动程序可与 OCI Instant Client 特性一起安装,不需要安装完整的 Oracle 客户端。有关更多信息,请参阅 Oracle Call Interface。
我们建议您优先使用 Oracle JDBC Thin 驱动程序,因为只有 JDBC Thin 驱动程序支持所有增强功能和新特性。
如果您使用的是非 TCP/IP 网络,您只能使用 OCI 驱动程序。
对于数据库会话中的就地处理(即数据库中 Java),您必须使用嵌入式 Type 2 驱动程序(或服务器内部驱动程序);如果会话中运行的 Java 代码需要访问远程 Oracle 数据库或同一数据库实例中的其他会话,您必须使用嵌入式 Type 4 驱动程序(或服务器 Thin 驱动程序)。
这两种驱动程序只能在 Oracle Server Java VM 中运行,它们的类将在安装 VM 时一同安装。因此,这两种驱动程序无可用的,也不需要单独的类文件。更多详细信息,请参阅 InternalT2Driver.java 和 InternalT4Driver.java。
如果您是第三方软件公司(或 Oracle 合作伙伴),请检查 FUTC 许可并与您的法务部门沟通,然后联系您当地的 Oracle 销售代表了解详情。
如果应用运行时启用了 SecurityManager(应用于生产环境),您可以执行特定操作。为了执行这些操作,您必须向代码授予相应的权限。
请查看下载页面上的 ojdbc.policy 文件,了解需要授予哪些权限。这是一个通用安全策略文件,您可以使用它来向驱动程序授予所有必要的权限。不过,绝大多数情况下,您可能希望撤销某些权限,因为您的应用不需要使用这些权限对应的特性。
该文件依赖许多系统属性。在使用前,您必须通过 java
命令的 -D 选项定义这些属性。
某些权限只需要向 JDBC 驱动程序代码开放,需要这些权限的操作封装在 doPriviliged
块中。另外,其他一些权限需要向调用驱动程序的代码开放,这些操作未封装在 doPriviliged
块中。一个典型例子是,当使用 Thin 驱动程序打开一个连接时,调用代码需要开放套接字权限,以此防止恶意代码使用驱动程序执行拒绝服务攻击或其他风险行为。
首先,请下载兼容您当前使用的 JDK 版本的 Oracle JDBC 驱动程序。您可以在下载页面上查找最新版本的 JDBC 驱动程序。然后,请确保将 JDBC 驱动程序放在类路径中。您可以查看......下载页面提供了哪些 JAR 文件?,确定您需要哪些文件。
JDBC OCI 驱动程序通常需要安装与驱动程序相同版本的 Oracle 客户端,不过,OCI Instant Client 特性提供了 JDBC OCI 驱动程序,您不需要完整安装 Oracle 客户端。请参阅 OCI Instant Client 安装文档,了解详细信息。
无需安装,这两种驱动程序将随数据库一同安装。如果数据库安装了 Java 支持,则这两个驱动程序已安装且可用。请参阅是否可以将一个类文件加载到 Oracle Server Java VM?,了解详细信息。
首个版本的 JDBC 指定使用类 java.sql.DriverManager
来创建连接。事实证明,这种方法不够灵活,于是后续版本的 JDBC 规范重新定义了一种方法,即使用 DataSource 创建连接。我们建议您使用 DataSource。
DataSource 提供了一种更灵活的方式来创建连接。它被设计为与 JNDI 配合使用,不过您也可以单独使用。DataSource 不仅可以创建新的连接,还可以实施连接缓存。现在,DataSource 已成为创建连接的首选方式。
以下是使用 DataSource 创建连接最简单的方法:
ds = new oracle.jdbc.pool.OracleDataSource();
ds.setURL(myURL);
conn = ds.getConnection(user, password);
请使用通用连接池 (UCP)。这种新的连接缓存机制具有驱动程序、协议和数据库无关的特点,支持您与 Oracle 以外的数据库建立 JDBC 连接和非 JDBC 连接。当使用 Oracle JDBC 时,它可以提供以下高级 Oracle 特性:
通用连接池不支持 Oracle Implicit Connection Cache。请注意,11.1 版本不支持旧连接缓存 OracleConnectionCacheImpl。
JDBC OCIConnectionPool 旨用于通过少量的底层实体数据库连接来池化多个有状态会话。它仅在调用持续期间将连接绑定到会话,以底层实体连接为元素,支持应用会话(内部)迁移到任何可用的底层实体连接。
池中每个实体连接都额外拥有一个面向服务器的内部会话,因此您会在服务器上看到更多数量的会话。
URL 的一般格式为:
jdbc:oracle:<drivertype>:<username/password>@<database>
<drivertype>
可选择:
thin
oci
kprb
<username/password>
可为空或使用以下格式:
<username>/<password>
注意,
用户名和密码为空的 URL 格式如下:
jdbc:oracle:thin:@mydatabase
此格式未指定用户名和密码。在使用此格式时,请务必以其他方式提供用户名和密码。
数据库描述的格式在一定程度上取决于驱动程序的类型。如果驱动程序类型为 kprb,数据库描述为空。如果驱动程序类型为 oci 且您希望使用 bequeath 连接,数据库描述同样为空。其他情况下(thin
或 oci
驱动程序且非 bequeath 连接),数据库描述应使用以下格式:
//<host>:<port>/<service>
<host>:<port>:<SID>
<TNSName>
以下 URL 使用 Thin 驱动程序,经由主机 myhost 端口 1521,通过密码 tiger
将用户 scott
连接到提供 orcl
服务的数据库(重要提示:参见 more on services)。
jdbc:oracle:thin:scott/tiger@//myhost:1521/orcl
以下 URL 未指定用户名和密码,使用 OCI 驱动程序和 SID
inst1 连接到同一数据库。
jdbc:oracle:oci:@myhost:1521:inst1
以下 URL 未指定用户名和密码,使用 Thin 驱动程序连接到 tnsnames.ora
文件中名为 GL 的数据库。用户名和密码必须以其他方式提供。
jdbc:oracle:thin:@GL
10.2.0.1.0 版本新增支持在 Thin 驱动程序中使用 TNSNAMES 条目。为了确保该特性工作运行,您必须正确配置 tnsnames.ora
文件。
除了 URL,您还可以使用标准 Java Properties
类对象作为输入。例如:
java.util.Properties info = new java.util.Properties();
info.put ("user", "scott");
info.put ("password","tiger");
info.put ("defaultRowPrefetch","15");
getConnection ("jdbc:oracle:oci:@",info);
关于 oracle.jdbc.OracleConnection
的 JavaDoc 明确定义了所有受支持的属性。JavaDoc 描述了用于定义属性名的一些常量,介绍了每个常量的功能及使用方法。
对于 11.1 版本之前的驱动程序,您可以通过关于 oracle.jdbc.pool.OracleDataSource.setConnectionProperties
的 JavaDoc 和 Oracle JDBC 开发人员指南查找受支持的属性。
DriverManager
注册 OracleDriver
类吗?您无需再注册 OracleDriver
类即可使用服务器端内部驱动程序进行连接 — 当然,注册也没有任何危害。无论您使用 getConnection()
还是 defaultConnection()
进行连接,都不需要注册。
如果您使用的是 ojdbc6.jar 和 JSE 6 或更高版本,无论使用哪一种驱动程序,您都无需注册驱动程序。自 JSE 6 起,标准 Java 服务提供者接口会自动注册驱动程序。您只需调用 DriverManager.getConnection
,运行时便会查找驱动程序并自动注册。
在连接到服务器默认连接时,URL 字符串中的所有用户名或密码都会被忽略。每次调用时,DriverManager.getConnection()
方法都会返回一个新的 Java Connection
对象。注意,尽管该方法不会创建新的数据库连接(仅使用单个隐式连接),但它会返回一个新的 java.sql.Connection 对象。
同样,当 JDBC 代码在目标服务器内部运行时,连接是一个隐式数据通道,而不是一个来自客户端的显式连接实例。任何时候,请勿关闭该通道。
请增加内存分配池的初始内存空间 (-ms) 和最大内存空间 (-mx)。11.1 和更高版本的驱动程序的内存需求低于 10g 版本,出现这一问题的概率较低。关于这一问题的详细信息,请参阅JDBC OTN Web 页面上的《JDBC 内存管理》白皮书。
Oracle 目前正使用一种新的服务方法取代 SID 数据库标识机制 — 新方法自 8.1.wi7 起可用。JDBC 的连接 URL 支持该服务方法。我们强烈建议所有用户尽快从 SID 过渡到服务方法,因为未来版本的数据库将不再支持 SID。
服务 URL 的基本格式为:
jdbc:oracle:thin:[<user>/<password>]@//<host>[:<port>]/<service> jdbc:oracle:oci:[<user>/<password>]@//<host>[:<port>]/<service>
示例:
jdbc:oracle:thin:@//myserver.com/customer_db jdbc:oracle:oci:scott/tiger@//myserver.com:5521/customer_db
更多信息,请参阅《JDBC 用户指南》。
唯一的方法是在连接时使用 Properties 对象,而不是在字符串中指定用户名和密码。您可以将用户名置于 "user" 属性中,将密码置于 "password" 属性中,然后将模式置于 "internal_logon" 属性中。如下所示:
Properties props = new Properties();
props.put("user", "scott");
props.put("password", "tiger");
props.put("internal_logon", "sysoper");
Connection conn = DriverManager.getConnection (url, props);
在 Thin 驱动程序下以 SYSDBA 或 SYSOPER 身份连接时,请对 RDBMS 进行相应配置,以使用密码文件。更多信息,请参阅《Oracle 数据库管理员指南》中的“创建和管理密码文件”部分。
JDBC OCI 驱动程序支持的算法与数据库服务器相同。
在 11.1 和 11.2 版本中,JDBC Thin 驱动程序支持:
在服务器配置正确的前提下,您可以使用以下连接属性:
Properties props = new Properties();
props.put("oracle.net.encryption_types_client", "(3DES168)");
props.put("oracle.net.encryption_client", "REQUIRED");
props.put("oracle.net.crypto_checksum_types_client", "(MD5)");
props.put("oracle.net.crypto_checksum_client", "REQUIRED");
代理身份验证支持一名用户通过另一名用户的身份进行连接。例如,代理身份验证支持中间层使用一个“通用”账户面向数据库进行“一次”验证,然后代表实际用户建立轻量级会话。更多信息,请参阅关于 oracle.jdbc.OracleConnection.openProxySession
的 JavaDoc。
是,但仅限特定驱动程序。具体而言,JDBC-OCI 驱动程序自 Oracle JDBC 9.2.x 起支持 SSL 加密,Thin 驱动程序自 10.2 起支持 SSL 加密。
是。例如,当使用 Oracle Internet Directory 作为 LDAP 提供程序时,JDBC Thin 驱动程序在连接 URL 中支持常规 LDAP 和基于 SSL 的 LDAP。更多信息,请参阅《Oracle JDBC 开发人员指南》和《Oracle Net Services 管理员指南》。
通常情况下,我们建议您使用 Oracle Connection Manager 作为代理进行连接。您只需要打开 Oracle Connection Manager 指定的端口,其他的将由 Oracle Connection Manager 完成。注意,请勿直接打开数据库监听程序正在使用的任何端口,如端口 1521。
关于如何配置 Oracle Connection Manager,请参阅《Oracle Net Services 管理员指南》。
defineColumnType
?我应当何时使用?defineColumnType
是一个Oracle JDBC 扩展,可在某些场景下提供更高的性能。在 Oracle JDBC 早期版本中,所有驱动程序都可以通过调用 defineColumnType
来优化性能。从 10.1.0 开始,Thin 驱动程序不再需要该扩展提供的信息,它无需调用 defineColumnType
即可实现最佳性能;而 OCI 和服务器端内部驱动程序仍然可以调用 defineColumnType
来提高性能。
如果您的代码需要使用 Thin 驱动程序和 OCI 驱动程序,您可以在使用 Thin 驱动程序时将连接属性 disableDefineColumnType
设置为 "true"
,以此禁用 defineColumnType
方法。这将使 defineColumnType
成为一个 NOOP。而在使用 OCI 或服务器端内部驱动程序时,请勿设置此连接属性,或者请将其设置为 "false"
。
您还可以使用 defineColumnType 来更改数据类型,或限制可变长度数据的大小。
defineColumnType 还通过使用第 4 个参数(用于 form_of_use)衍生出了一个新的变体。
defineColumnType
是否会在服务器上强制执行转换操作?defineColumnType 在 Thin 驱动程序下会强制执行转换操作,但在 OCI 和服务器端内部驱动程序下不会。
请使用 OracleConnection 中的 'CONNECTION_PROPERTY_PROCESS_ESCAPES' 属性。
会,您可以参阅 JavaDoc oracle.jdbc.OraclePreparedStatement
,查找 setXXXAtName
方法。此外,oracle.jdbc.OracleCallableStatement
还支持通过正式参数名称将参数绑定到 PL/SQL 程序。有关 oracle.jdbc.OracleCallableStatement.setXXX(String, ...)
方法,请参阅 JavaDoc。
请注意,setXXX(String, XXX)
使用(被调用的)已存储程序的正式参数名称执行绑定,setXXXAtName(String, XXX)
使用(执行中的)SQL 字符串中的 Oracle 式 ( :foo
) 参数名称执行绑定。这两种语句区别很大,生成的结果也大相径庭。
通常来说,每种 setXXX 方法都固定关联一种对于参数类型最为合理的数据类型。
数据将以适用于预设数据类型的格式被发送到服务器,随后服务器会尝试将其转换为目标参数的类型。如果无法转换,服务器会提示错误,驱动程序会在执行时抛出 SQLException。
对于 SQL 语句,我们可以先前往服务器获取类型信息,然后再进行转换,但这会产生额外的往返时间。因此,我们针对常见场景(JDBC 程序员针对列类型使用最适当的 API)进行了代码优化。
对于字节数据,Oracle SQL 支持三种类型:RAW、LONG RAW 和 BLOB。RAW 数据长度有限,它直接存储在列中并以内联数据包的形式传输到服务器。LONG RAW 数据具有更严格的限制 (2 Gigabyte),它通过一种特殊的行旁机制存储并通过流回调机制传输到服务器。BLOB 数据的长度不受限制,它与表分开存储(只在表中存储一个 LOB 定位器),须在将定位器存储到表的列之前通过单独操作传输到服务器。
对于字节数据,Oracle SQL 支持三种类型:VARCHAR2、LONG 和 CLOB。VARCHAR2 数据长度有限,它直接存储在列中并以内联数据包的形式传输到服务器。LONG 数据的最大限制为 2 Gb,它通过一种特殊的行旁机制存储并通过流式回调机制传输到服务器。BLOB 数据的长度不受限制,它与表分开存储(只在表中存储一个 LOB 定位器),须在定位器存储到表的列之前通过单独操作传输到服务器。
格式 | Stmt | 驱动程序 | 下限 | 上限 | 绑定机制 | 备注 |
---|---|---|---|---|---|---|
所有 | 所有 | 所有 | 0 | 0 | Null | |
所有 | SQL | 客户端 | 1 个字符 | 32766 个字符 | 直接 | |
所有 | SQL | 客户端 | 32767 个字符 | 2147483647 字节 | 流 | |
所有 | SQL | 客户端 | 2147483648 字节 | 2147483647 个字符 | 临时 Clob | |
CHAR | 服务器 | 1 个字符 | 65536 字节 | 直接 | 1, 2 | |
NCHAR | 1 个字符 | 4000 字节 | 直接 | |||
NCHAR | 4001 字节 | 2147483647 个字符 | 临时 Clob | |||
CHAR | 65537 字节 | 2147483647 字节 | 流 | |||
2147483647 字节 | 2147483647 个字符 | 临时 Clob | ||||
所有 | PL/SQL | 所有 | 1 个字符 | 32512 个字符 | 直接 | |
所有 | PL/SQL | 所有 | 32513 个字符 | 2147483647 个字符 | 临时 Clob |
Stmt | 驱动程序 | 下限 | 上限 | 绑定机制 | 备注 | |
---|---|---|---|---|---|---|
所有 | 所有 | 所有 | 0 | 0 | Null | |
所有 | SQL | 客户端 | 1 个字符 | 32766 个字符 | 直接 | |
所有 | SQL | 客户端 | 32767 个字符 | 2147483647 字节 | 流 | |
所有 | SQL | 客户端 | 2147483648 字节 | 2147483647 个字符 | 临时 Clob | |
CHAR | 服务器 | 1 个字符 | 65536 字节 | 直接 | 1, 2 | |
NCHAR | 1 个字符 | 4000 字节 | 直接 | |||
NCHAR | 4001 字节 | 2147483647 个字符 | 临时 Clob | |||
CHAR | 65537 字节 | 2147483647 字节 | 流 | |||
2147483647 字节 | 2147483647 个字符 | 临时 Clob | ||||
所有 | PL/SQL | 所有 | 1 个字符 | 32512 个字符 | 直接 | |
所有 | PL/SQL | 所有 | 32513 个字符 | 2147483647 个字符 | 临时 Clob |
注:
可替换为
Insert into blob_tab (blob_col) values (? );
API | 格式 | Stmt | 驱动程序 | 下限 | 上限 | 绑定机制 | 注意 |
---|---|---|---|---|---|---|---|
setBytesForBlob | n/a | 所有 | 所有 | 0 | 0 | Null | |
所有 | 客户端 | 1 字节 | 2000 字节 | 直接 | |||
所有 | 客户端 | 2001 字节 | 21474836487 字节 | 临时 blob | 2 | ||
setStringForClob | 所有 | 所有 | 所有 | 0 | 0 | Null | |
所有 | 所有 | 客户端 | 1 个字符 | 32766 个字符 | 直接 | ||
所有 | 所有 | 客户端 | 32767 个字符 | 2147483647 个字符 | 临时 Clob | ||
所有 | 所有 | 服务器 | 1 个字符 | 4000 字节 | 直接 | ||
所有 | 所有 | 服务器 | 4001 字节 | 2147483647 个字符 | 临时 Clob | 1 |
注:
会,
CallableStatements
和程序中使用 IN OUT
参数?IN 和 OUT 参数的数据类型必须一致,否则自动切换将导致冲突,除非用户代码在 registerOutParameter 中也更改了数据类型。因此,我们不建议使用 IN OUT 参数。您可以更改原始程序,添加一个使用单独 IN 和 OUT 参数的 wrapper 程序或 PL/SQL 块。
会,您可以考虑在 PL/SQL 代码中利用这一点。
现有代码将继续正常运行。只有一点发生了变化。以前,如果输入超出 API 的大小限制,调用 setXXX API 时将抛出 SQLException 异常。现在,这个异常会在执行时出现。
是。在下次执行该语句或关闭语句时,驱动程序将释放这些 lob。
会,但驱动程序无法决定是否切换至预设为最大字符串长度的 Clob。
我们建议不要创建超大型字符串。请查看您的 Java 虚拟机提供商文档,了解超大型对象对 Java 内存管理系统的影响。
LONG RAW
和 LONG
列类型已经弃用,为什么还要使用 setXXXStream
API?Stream API 至今仍未过时。对于某些操作,它们可以提供相比 LOB API 更高的性能,未来仍将继续发挥作用。
当然!LOB API 支持随机访问 LOB 的任何部分,您可以考虑在适当情形下利用这一特性。
select * from tab where id in (?, ?, ?, ...)
?因为对于 IN 子句中的元素,RDBMS 不支持绑定参数。这是数据库的局限性而不是驱动程序。
如果您试图在关闭一个 ResultSet 后使用它,或者关闭创建 ResultSet 的语句,这一错误提示就会出现。
ResultSet rset = stmt.executeQuery ("select ROWID from EMP"); ... rset.close (); // or stmt.close (); rset.getString (1);
原始 JDBC 规范要求在不再可用时必须关闭 Connection、Statement 和 ResultSet。这需要使用终结器。然而,无论使用何等终结器,终结器都会严重影响 JVM 中运行的应用各方面的性能。因此,Sun 强烈不建议使用终结器。自动关闭赖以实现的终结器对所有客户都是不利的,无论他们是否使用自动关闭特性。这显然不是一个合理的选择。
据我们所知,没有任何提供商的 JDBC 驱动程序实施或实施过自动关闭。同时,这一要求已被 JDBC 规范删除,只是在某些地方仍有一些残余,例如 JDBC 教程。JDBC 教程虽然内容丰富且大有帮助,但它不是权威信息,且已经多年没有更新了。目前,最新的 JDBC 4.0 规范已不要求自动关闭。
ResultSet、Statement 和 Connection 都会占用客户端和服务器资源:只要打开就会分配相关资源,只有在关闭时资源才会释放。如果不关闭 ResultSet、Statement和/或 Connection,将会导致资源泄漏和应用性能下降。
关闭一个 Connection,所有相关的 Statement 都会关闭;关闭一个 Statement,所有相关的 ResultSet 都会关闭。因此,当您使用 Connection 时,您只需关闭 Connection,所有相关 Statement 和 ResultSet 都会关闭。除了这种编程实践外,您还可以在最终块中显式关闭 Statement 和 ResultSet。这可以提高应用性能,在避免资源泄漏的情况下满足不断变化的需求。
PreparedStatement ps = null; ResultSet rs = null; try { ps = conn.prepareStatement(sql); try { rs = ps.executeQuery(); while (rs.next()) { // process row } } finally { if (rs != null) rs.close(); } } finally { if (ps != null) ps.close(); }
DATE
和 TIMESTAMP
?本节将介绍一些基本数据类型。:-)
在 9.2 以前的版本中,Oracle JDBC 驱动程序将 DATE
SQL 类型映射到 java.sql.Timestamp
。这在一定程度上是有意义的,因为 Oracle DATE
SQL 类型与 java.sql.Timestamp.
一样都包含了日期和时间信息。相比之下,将 DATE 映射到 java.sql.Date
会带来明显的问题,因为 java.sql.Date
不包含时间信息。此外,RDBMS 不支持 TIMESTAMP
SQL 类型,将 DATE
映射到 Timestamp
也没有问题。
在 9.2 版本中,RDBMS 新增了 TIMESTAMP
支持。DATE
与 TIMESTAMP
的区别在于 TIMESTAMP
可以精确到纳秒,DATE
不能。因此,从 9.2 版本开始,DATE
被映射到 Date
,而 TIMESTAMP
被映射到 Timestamp
。如果您的 DATE
值中包含时间信息,您可能会遇到问题。
对于 9.2 到 10.2 版本的驱动程序,您可以使用以下几种方法来解决这个问题:
TIMESTAMP
替代 DATE
。这是最佳解决方法,但成功几率很小。defineColumnType
将列定义为 TIMESTAMP
而不是 DATE
。不过,defineColumnType
可能是您无计可施时的最后选择(参见什么是 defineColumnType
?我应当何时使用?部分)。getTimestamp
替代 getObject
。这是一个很好的解决方法,但由于很多应用含有依赖 getObject
的通用代码,因此使用场景并不多。V8Compatible
连接属性。这可以指示 JDBC 驱动程序使用旧映射而不是新映射。您可以将标志设置为连接属性或系统属性。设置连接属性:将连接属性添加至 java.util.Properties
对象,然后传递给DriverManager.getConnection
或 OracleDataSource.setConnectionProperties
。设置系统属性:在 java
命令行中置入 -D
选项。Oracle JDBC 11.1 修复了这一问题。从这个版本开始,驱动程序默认将 SQL DATE 列映射至 java.sql.Timestamp
,您无需设置 V8Compatible
即可获得正确的映射。V8Compatible 已经严重过时,我们不建议您使用,即使将 V8Compatible 设置为 true 不会造成任何负面影响。
V8Compatible
很少用于上述场景,因为它不是为了解决 DATE 到 Date 的映射问题的,而是为了兼容 8i 数据库的:8i 及更早版本的数据库不支持 TIMESTAMP 类型。设置 V8Compatible
,不仅会在执行数据库读取操作时导致 SQL DATE 映射到 Timestamp,还会在执行数据库写入操作时导致所有 Timestamps
被转换为 SQL DATE。自 8i 数据库取消 V8Compatible 后,11.1 JDBC 驱动程序便不再支持这一兼容模式。这就是我们不再支持 V8Compatible
的原因。
如上所述,11.1 驱动程序默认在执行数据库读取操作时将 SQL DATE 转换为 Timestamp
。这个做法是正确的,9i 版本的改动是错误的,11.1 版驱动程序又恢复到了正确做法。即便您未在应用中设置 V8Compatible
,大多数情况下也不会出现任何行为差异。而如果使用 getObject 读取 DATE
列,您可能会发现一些差异:读取结果将显示为 Timestamp
而不是 Date
。由于 Timestamp
是 Date
的子类,所以通常不会出现问题。如果您通过将 DATE
转换为 Date 来截断时间组件,或者对值应用 toString,您可能会发现一些差异。否则,更改应该是透明的。
如果出于某种原因,您的应用对这一更改非常敏感且您必须执行 9i-10g 行为,您可以设置连接属性。通过将 mapDateToTimestamp
设置为 false,驱动程序将恢复到默认的 9i-10g 行为并将 DATE 映射到 Date
。
方法 | 列类型 | 最大长度 |
---|---|---|
setBytes |
LONG |
4k 字节 |
setBytes |
LONG RAW |
2G 字节 |
setString |
LONG |
32k 字符 (SetBigStringTryClob="false" )4k 字符 ( SetBigStringTryClob="true" ) |
setString |
CLOB |
2G 字符 |
在 9.2 版本中,作用于 LONG 的 setString() 在 OCI 驱动程序下最多可插入 64k 字符,在 Thin 驱动程序下最多可插入 4k 字符。在 10.1.0 版本中,setString() 在这两个驱动程序下可插入字符的上限为 32k 字符。将 OCI 驱动程序下的可插入字符上限从 64k 降低到 32k 可能会对某些客户产生影响,但考虑到这种变更带来的巨大的性能提升,我们决定更改架构,并强烈建议从 LONG 迁移到 CLOB。
我们建议需要使用 setString() 来处理超过 32000 个字符的客户从 LONG 迁移到 CLOB。
TIMESTAMP WITH TIME ZONE
会出现不同的结果?旧行为是错误的,详见 Bug 4322830。
旧行为是构建一个 Timestamp
,它输出的值与数据库值相同。但是,由于 Timestamp
使用 UTC 时区,提供的 Timestamp
值与正确的值存在偏差,例如国际标准时间 (UTC) 2007 年 1 月 1 日上午 8:00 与太平洋标准时间 (PST) 2007 年 1 月 1 日上午 8:00 是不同的,它们分别代表不同的时间点。
如果您从数据库中读取的时间为太平洋标准时间 (PST) 2007 年 1 月 1 日上午 8:00,那么 9i 和 10g 驱动程序将构建一个值为国际标准时间 (UTC) 2007 年 1 月 1 日上午 8:00 的 Timestamp
。虽然输出的“2007 年 1 月 1 日上午 8:00”看似正确,但它代表的时间点显然是错误的。11.1 驱动程序已修复这一 Bug。
JDBC 4.0 针对 Connection
接口引入了工厂方法来创建 ADT 实例。这一 API 比构造器更加优秀,我们强烈建议您尽可能使用工厂方法,因为我们即将淘汰构造器并取消构造器支持。
由于标准工厂方法是在 JDBC 4.0 引入的,所以这些方法只在 JSE 6 驱动程序(ojdbc6.jar) 下可用。对于 Oracle 专用数据类型的的创建,OracleConnection
面向 JSE 5 和 JSE 6(ojdbc5.jar 和 ojdbc6.jar)定义了工厂方法。我们再次强烈建议您使用工厂方法。
createArrayOf
?SQL 标准数组类型是匿名的,类型 "array of foo" 没有名称,仅对元素类型进行了命名。而在 Oracle SQL 中,数组类型是命名的。Oracle SQL 不支持匿名数组。因此,JDBC 4.0 标准工厂方法使用元素类型作为参数来创建匿名数组类型实例。Oracle JDBC 驱动程序定义了一个 Oracle 专用方法 createArray
,该方法可接受数组类型名称并返回该命名数组类型的实例。这符合 Oracle SQL 的要求。目前,Oracle 数据库尚不支持 JDBC 4.0 标准 createArrayOf
方法。
它可用于“清理” CLOB 的段,但它 * 不会 * 缩短 CLOB,执行 ERASE 后,CLOB 的长度不会改变。如需缩短 CLOB,请使用 DBMS_LOB.TRIM。
可以,但您必须确保位置和长度参数正确。您还可以使用推荐的 OutputStream 接口,它可以为您调用 putChar。
在 JDBC 中,CLOB *始终*使用 USC2 编码(这是与 Java “char” 类型对应的 Oracle 字符集)。因此对于 OCI CLOB CharSetId,JDBC 没有提供对等的函数。
这取决于具体情况。当写入值小于 10K 时,LONG RAW 的速度更快。当写入较大值时,两者速度几乎没有差异。
这是合理的。LONG 列不支持就地“提取”(即行内提取)。在提取后,LONG 列将一直存储在管道中直到您显式读取。在这种情况下,我们一般会得到一个 LobLocator (getBlob()),然后在读取 LONG 列之前尝试获取该 LOB 的长度。由于管道不明确,我们会遇到上述异常。对此,解决方法是先完成 LONG 列读取,然后再对 BLOB 执行其他操作。
Oracle LOB 使用值语义。更新 LOB 时,您必须将 LOB 写回数据库,才能在数据库中看到更改。由于技术原因,有时即使您不写回 LOB,数据库也会保存您的更改。但为了避免意外,我们建议您每次都将 LOB 写回数据库。
这是以前,而非现在。现在 REF 支持序列化。
如果您当前使用的是不支持 REF 序列化的旧版本 Oracle JDBC 驱动程序,请注意以下事项。
REF 类的重要组成部分包括表示所引用对象的字节数组以及对象类型的全限定名。您可以使用类似 "SomeREF" 的类来保存对象 REF 的字节和类型名。这种类是支持序列化的,它可以使用以 JDBC Connection 作为参数的 "toREF" 方法重新创建 REF。
公共类 SomeREF 实施 java.io.Serializable { String typeName; byte[] bytes; public SomeREF (oracle.sql.REF ref) throws SQLException { this.typeName = ref.getBaseTypeName (); this.bytes = ref.getBytes (); } public oracle.sql.REF toREF (Connection conn) throws SQLException { return new oracle.sql.REF (new oracle.sql.StructDescriptor (typeName,conn),conn, bytes); } }
您可以对包含 REF 到 Oracle8 对象类型的表执行查询,然后 JDBC 会将 REF 具体化为 Java oracle.sql.REF 对象。JDBC 不支持从头创建新的 REF,您只能前往数据库,在 SQL 中插入新 REF,然后选择 REF 并将其返回客户端。
您也可以使用 PL/SQL 块,这样更简单。例如,如果您拥有下表:
create or replace type point as object (x number, y number); create table point_values_table of point; create table point_ref_table (p ref point); 您可以在 point_values_table 中插入一个新的点值,在 point_ref_table 中插入一个新 REF,然后将 REF 返回到客户端,代码如下: oracle.jdbc.driver.OracleCallableStatement call = (oracle.jdbc.driver.OracleCallableStatement) conn.prepareCall ("declare x ref point; " + "begin insert into point_values_table p values (point(10, 20))" + " returning ref(p) into x; " + " ? := x; " + "end;"); call.registerOutParameter (1, oracle.jdbc.driver.OracleTypes.REF,"SCOTT.POINT"); call.execute (); oracle.sql.REF ref = (oracle.sql.REF)call.getObject (1);
OPAQUE 类型拥有二进制数据和服务器本机代码库定义的支持方法,它仅供 Oracle 内部使用。
Bean 的属性可分为:
对象创建属性应在创建对象之前设置,因为对于对象创建而言它们属于关键属性。运行时属性可以随时设置,它们会在运行时更改 Bean 的行为。
可滚动性、用户名和密码属于对象创建属性。自动提交状态、预取计数等属于运行时属性。后台对象通常会在 execute/setCommand 期间启动,因此所有 Statement 创建属性都应在此之前设置好。由于创建 Statement URL 需要一个连接对象,因此用户名、密码等都应在设置 Command 前设置好。
可以。可序列化流支持您将流对象序列化到任何可序列化的介质,例如平面文件、网络连接等。此特性仅适用于 CachedRowSet。您可以在安装了 JDBC 驱动程序的设备上创建 CachedRowSet,然后将其移动到仅安装 RowSet 二进制文件,但未安装驱动程序二进制文件的远程客户端。远程客户端可以对 RowSet 执行插入、删除或更新等更改操作。然后,您可以将 RowSet 发回安装了 JDBC 驱动程序和 RowSet 二进制文件的设备,将修改后的值同步到数据库中。
可以。Thin JDBC 驱动程序可用于开发 Java 应用,但与 JDBC OCI 驱动程序不同,它仅适用于基于 TCP/IP 的网络。如果您基于非 TCP/IP 网络运行应用,我们建议使用 JDBC OCI 驱动程序。
当您在一个 Java 存储过程中访问数据库时,请使用服务器内部驱动程序。Java 存储过程是一种在 Oracle RDBMS 中执行的 Java 方法,就像在 RDBMS 中执行 PL/SQL 一样。因为它在 RDBMS 中执行,所以必然在数据库会话中执行。服务器内部驱动程序连接则是该会话的句柄。所以,如果您的代码在 Java 存储过程中运行并且您希望访问数据库,您可以使用服务器内部驱动程序(仅少数情况下需要使用服务器 Thin 驱动程序)。
服务器内部驱动程序一般适用于 Java 存储过程,它连接到与存储过程于其中执行的同一会话。但有时您可能希望连接到另一个数据库或同一数据库中的新会话。在这两种情况下,请使用服务器 Thin 驱动程序。
请确保驱动程序已注册且您使用的连接 URL 与 JDBC 驱动程序一致。您可以查看“使用 Oracle JDBC 驱动程序”,了解正确的值。
使用 Win NT 或 Win95 时,当 OCI73JDBC.DLL 调用的一个 DLL 无法加载时,Java 虚拟机就会提示无法加载 OCI73JDBC.DLL。JDBC OCI 驱动程序使用包含驱动程序 C 代码的共享库。对于 Oracle7 客户端程序,这一共享库是 OCI73JDBC.DLL。在您通过发行版安装 JDBC 驱动程序时,共享库通常一并安装在了 [ORACLE_HOME]\BIN 中。请务必确保该目录在您的 PATH 中。更多详细信息,请参阅该文档的“安装”部分。
共享库还依赖其他库,其中的任何 DLL 缺失都会导致 "OCI73JDBC.DLL is missing" 错误。JDBC OCI7 需要以下 Oracle7 文件:CORE35.DLL、CORE35O.DLL、NLSRTL32.DLL 和 ORA73.DLL。
Java 虚拟机 (JavaSoft JDK) 需要 JAVAI.DLL。
Microsoft Visual C++ 运行时需要 MSVCRT.DLL、MSVCRTI.DLL、MSVCRT20.DLL 和 MSVCRT40.DLL。
您可以打开 Windows 资源管理器,右键单击 DLL 并选择 Quick View,查找相关 DLL 的列表。“Quick View” 界面还会显示列出了相关 DLL 的引入表。您可以通过 Oracle 安装 CD 重新安装缺少的支持文件。我们建议您安装 "Required Support Files 7.3.4"、"SQL*Net Client 2.3.4" 和 "Oracle TCP/IP Protocol Adapter 2.3.4"c。
您当前在 Oracle7 客户端安装中使用的是 OCI8 驱动程序,请使用 OCI7 驱动程序。
客户端在一次连接中可打开的游标数量是有限的(默认值为 50)。您可以使用 stmt.close() 方法来显式关闭语句,关闭和释放游标,
如果您没有显式关闭游标,您就可能遇到这一错误。您可以通过调高 "OPEN_CURSORS" 参数来避免这一问题,但这种方法治标不治本,只能维持一段时间。请显式关闭您不再需要的游标。
JDBC 连接默认打开 AutoCommit,但是在使用包含 'for update' 的 SQL 前,您需要关闭 AutoCommit。
因此,您只需将 AutoCommit 设置为 false 即可。
请显式设置 NLS_LANG。如果未设置 NLS_LANG,或已正确设置但仍报错,您使用的可能不是 Oracle7.3.4。请安装 Oracle7.3.4 客户端。
客户端上未安装或未正确安装 Oracle。如果您尚未执行安装操作,请使用常规的 Oracle 服务器安装 CD 执行“Oracle 客户端”安装,将必要的软件安装在客户端上。如果您已执行安装操作,请检查是否已正确安装,如有必要,请移除并重新安装。
注意,如果在安装客户端时未设置 ORACLE_HOME,您也可能会遇到这一错误提示。如果缺少 ORACLE_HOME 环境变量,您只需设置/导出该环境变量即可解决问题,无需重新安装客户端。
JDBC Thin 驱动程序要求为包含 Unicode 字符的文字添加双引号。例如:
ResultSet rset = stmt.executeQuery ("select * from \"\u6d82\u6d85\u6886\u5384\"");
驱动程序默认在执行语句时立即提交所有 INSERT和 UPDATE 操作,这便是 JDBC 的 autoCommit 模式。如需提高性能,您可以关闭 autoCommit,显式提交语句。请使用 Connection 类 setAutoCommit 入口点关闭 autoCommit:
connection.setAutoCommit(false);请查看 JDBC 文档中关于批量更新的内容,了解针对 INSERT 和 UPDATE 的 Oracle 批量调用扩展。相比关闭 autoCommit,命令批处理的速度更快。
如果在连接到服务器时服务器崩溃,通常会出现这个错误提示 — 无论您正在建立连接还是已建立连接。对此,请检查服务器端日志文件,查看服务器抛出了哪些错误和堆栈快照。
请注意,该错误与您尝试连接错误/无效端口甚至计算机时的情况不同,与服务器关闭且不接受连接请求时的错误提示也不同。
当 Thin 驱动程序从 RDBMS 读取了预期以外的内容时,就会抛出这一异常提示。这意味着 Thin 驱动程序中的协议引擎与 RDBMS 中的协议引擎不同步。一旦出现这个错误,您将无法恢复,连接将挂死。您可以尝试关闭连接,但很可能无效。
如果您收到生成该错误的可重现测试用例,请将 TAR 提交给 Oracle 全球支持团队。提交时,请注明 JDBC 驱动程序和 RDBMS 的版本号,包括所有已安装的补丁程序。
是,在 UNIX 系统上,请前往 $ORACLE_HOME/jdbc/demo/demo.tar
获取演示程序;在 Windows 系统上,请前往 $ORACLE_HOME/jdbc/demo/demo.zip
获取演示程序。
解压 demo.tar
或 demo.zip file
,您将看到一个 Samples-Readme.txt 文件。请首先阅读该文件,大致了解 JDBC 演示程序,然后在 UNIX 上运行 Makefile
,或在 Windows 上运行 rundemo.bat
。
正常情况下,JDBC 演示程序运行不会出错。如果出现错误,可能是您的配置存在问题。请检查以下项目:
Samples-Readme.txt、Makefile
以及每个 .java 文件,了解预测试要求。JDBC 跟踪工具是之前版本的 Oracle JDBC 内置的运行时调试辅助工具。启用后,它将输出关于 Oracle JDBC 驱动程序的执行信息,通常包括方法进入、参数值、重要内部状态、内部错误、方法退出和返回值。
从 10.1.0 开始,仅 classes12_g.jar 和 classes12dms_g.jar 支持这一 Oracle 跟踪工具。所有支持 1.4 及更高版本 JDK 的 Oracle JDBC 驱动程序现在都使用 java.util.logging 内置的跟踪工具。您可以查看 java.util.logging 部分内容,了解在使用 JDBC 11、ojdbc14_g.jar 或 ojdbc14dms_g.jar 时如何获取跟踪信息。
当您在使用 JDBC 应用的过程中遇到困难时,您就会发现跟踪工具的优势。虽然它提供的大多数信息都是关于内部 JDBC 方法的,比较模糊,但您仍能从中得到帮助。我们建议您从将跟踪量设置为 1 开始。
如果您认为 JDBC 中存在 Bug,跟踪功能有助于我们为您提供帮助。在这种情况下,请不要变更跟踪量的默认值。由于这会产生大量输出,您可以先跟踪一个小型测试用例或者一个大型应用的一部分。对此,请使用适当的代码。
您可以查看 java.util.logging 部分的内容,了解如何在使用 JDBC 11 时获取跟踪信息。
要使用 JDBC 跟踪工具,您必须使用调试 Jar 文件:classes12_g.jar 或 classes12dms_g.jar。如果您试图在使用其他 Jar 或 Zip 文件时使用跟踪工具,跟踪工具将不会输出任何内容,或者您将会收到一条错误信息。
您可以通过两种方法控制跟踪工具:编程和属性。编程 API 支持您在执行应用时启用或禁用跟踪并更改其他属性。考虑到庞大的跟踪数据量,我们建议只对特别可疑的代码启用跟踪。如果难以更改应用源,您也可以通过属性来控制跟踪工具 — 跟踪属性只会在应用启动时读取一次。您也可以同时使用属性和 API,即通过属性设置初始状态,使用 API 来更改状态。
通过编程启用跟踪的最简单的方法是调用
oracle.jdbc.driver.OracleLog.startLogging();这会将跟踪信息发送到 System.out。如需关闭,请调用
oracle.jdbc.driver.OracleLog.stopLogging();您也可以通过将系统属性 oracle.jdbc.Trace
设置为 "true"
来启用跟踪。通过对以下所有 JDBC 跟踪工具属性执行 java -Doracle.jdbc.Trace=true MyApp Setting,您可以隐式将 oracle.jdbc.Trace
设置为 "true"
。
您可以查看 java.util.logging 部分的内容,了解如何在使用 JDBC 11 时获取跟踪信息。
JDBC 跟踪工具可以生成大量输出。控制输出量最简单的方法就是仅在需要时启用跟踪:
oracle.jdbc.driver.OracleLog.startLogging(); myApp.suspectCode();
oracle.jdbc.driver.OracleLog.stopLogging(); 这通常不可用。您也可以通过设置跟踪量来减少跟踪的信息量。oracle.jdbc.driver.OracleLog.setLogVolume(1);默认值为 2,最大值为 3。但是,设置为 3 时的输出仅多于 2 一小部分,设置为 1 时的输出比设置为默认值时少得多。
您可以通过显式设置行长度或更改每行输出的字段来控制每行的长度。要想更改最大行长度,请执行
oracle.jdbc.driver.OracleLog.setMaxPrintBytes(100);或 java -Doracle.jdbc.MaxPrintBytes=100 MyApp。
您可以通过设置属性 oracle.jdbc.PrintFields 来控制输出哪些字段。
java -Doracle.jdbc.PrintFields=none MyApp 的有效值为:
您可以查看 java.util.logging 部分的内容,了解如何在使用 JDBC 11 时获取跟踪信息。
跟踪输出默认发送至 System.out
。您也可以使用属性 oracle.jdbc.LogFile
来将其发送至其他位置:
java -Doracle.jdbc.LogFile=/tmp/jdbc.log MyApp;或调用 setLogStream API:oracle.jdbc.driver.OracleLog.setLogStream(System.err);您也可以通过设置日志流来启动跟踪,通过将日志流设置为空值来关闭跟踪。
请使用系统属性 oracle.dms.console.DMSConsole。在未设置该属性的情况下,DMS 处于活动状态。您可以将其设置为 oracle.dms.instrument_stub.DMSConsole,通过存根实施来有效禁用 DMS。应用可以在执行所有 DMS 代码前,通过调用
System.setProperty( "oracle.dms.console.DMSConsole","oracle.dms.instrument_stub.DMSConsole"); 来禁用 DMS。另一种方法是将 -D 选项嵌入 Java VM:java -Doracle.dms.console.DMSConsole=oracle.dms.instrument_stub.DMSConsole MyApp
否。Oracle 已不再支持 Visual Cafe。
否。Oracle 已不再支持 Visual J++。
是。Oracle JDBC OCI 驱动程序和 Thin JDBC 驱动程序都支持执行 PL/SQL 存储过程和匿名块,都支持 SQL:2003 转义语法和 Oracle 转义语法。以下 PL/SQL 调用在这两种 Oracle JDBC 驱动程序下均可用:
是。Oracle JDBC OCI 驱动程序和 Thin JDBC 驱动程序都支持客户端和服务器之间的双向数据流处理。它们支持所有流转换,如二进制、ASCII 和 Unicode。更多信息,请参阅 Oracle JDBC 驱动程序文档中流相关的教程内容。
支持。Oracle JDBC OCI 驱动程序和 Thin JDBC 驱动程序都支持多字节字符集,都可以访问基于任意 Oracle 字符集的数据库,并能够将多字节字符转换为 Unicode 1.2。经测试,JDBC OCI 驱动程序支持所有欧洲字符集以及包括中文、日语和韩语在内的所有亚洲字符集。
是。JDBC OCI 驱动程序和 Thin JDBC 驱动程序都可以在内联网和外联网设置下运行。在外联网部署中,JDBC 驱动程序兼容 SQL*Net 认证的大多数防火墙。以下提供商的防火墙已获得 SQL*Net 认证:
否。Oracle JDBC 驱动程序不支持 PL/SQL 类型表(现被称为索引表)、结果集、记录或布尔值的调用参数或返回值,暂时也没有引入这些支持的计划。我们建议您使用 RefCursor、Oracle Collection 和结构化对象类型。
此外,您可以创建 wrapper 程序,以 JDBC 支持的数据类型格式来处理数据。
例如,为了包装使用 PL/SQL 布尔值的存储过程,您可以创建一个存储过程来从 JDBC 获取字符或数字,然后以布尔值格式传递到原始过程;或者,对于输出参数,接受来自原始过程的布尔值参数并将其以 CHAR 或 NUMBER 格式传递到 JDBC。同样,要包装使用 PL/SQL 记录的存储过程,您可以创建一个存储过程,在各个组件(如 CHAR 和 NUMBER)中处理记录。要包装使用 PL/SQL 表的存储过程,您可以将数据拆分,也可以使用 Oracle 集合类型。
以下是一个面向存储过程 (PROC) 的 PL/SQL wrapper 过程 (MY_PROC) 示例,它接受布尔值输入:
PROCEDURE MY_PROC (n NUMBER) IS BEGIN IF n=0 THEN proc(false); ELSE proc(true); END IF; END; PROCEDURE PROC (b BOOLEAN) IS BEGIN ... END;
会,当连接到 RAC 服务器时,Fast Connection Failover(快速连接故障转移)可快速响应故障事件。这一全新的高可用性特性与驱动程序无关,可与隐式连接缓存和 RAC 配合使用,通过缓存实现最高的连接可用性。它可以处理 RAC 停机事件,移除无效连接和恢复 RAC 运行,实现现有连接负载均衡。
如果您使用的是 OCI 驱动程序且您只需要查询故障转移特性,您可以考虑使用 TAF。TAF 主要用于在应用中执行查询故障转移,采用了独特的故障转移机制。注意,Fast Connection Failover 和 TAF 无法同时使用,一次只能使用一个。
我们不支持 getCursorName 和 setCursorName JDBC 入口点,但支持访问具有类似功能的 ROWID。JDBC 4.0 定义了 java.sql.Rowid
,它与 oracle.sql.ROWID
完全兼容且在 JSE 6 (ojdbc6.jar) 驱动程序下可用。
将 ROWID 伪列添加到查询后,您可以使用 ResultSet getString 入口点在 JDBC 中检索它,也可以使用 setString 入口点将 ROWID 绑定到一个 preparedStatement 参数。
它支持就地更新,如下例所示:
在 ResultSetMetaData 类中,包含 ROWID 的列由 oracle.jdbc.driver.OracleTypes.ROWID 类型报告,值为 -8。
Oracle JDBC 驱动程序支持 REFCURSOR 类型的绑定变量,一个 REFCURSOR 由一个 JDBC ResultSet 表示。您可以使用 CallableStatement 的 getCursor 方法,将 PL/SQL 块返回的 REFCURSOR 值转换为 ResultSet。JDBC 允许您调用(执行查询并返回 ResultSet 的)存储过程。您可以通过将相应的 CallableStatement 转换为oracle.jdbc.driver.OracleCallableStatement 来使用 getCursor 方法。
9.2 及更高版本的 OCI 和 Thin 驱动程序都支持 ANO。
8.0.x 及更高版本的 OCI 驱动程序支持 ANO。对于 8.0.4、8.0.5 和 8.0.6 版本,您需要安装最新的补丁集才能使用 ANO 特性。
注意:8.1.5 和 8.1.6sdk 中存在一个已知 Bug (#899424)。虽然我们进行了修补,但尚未将其作为补丁程序反向移植和发布到以前的所有版本。到目前为止,这个 Bug 在 8.1.5 和 8.1.6sdk 中仍然存在。
8.1.6 已经在代码中对上述 Bug 进行了修复,因此不安装补丁也可以正常运行!有关更多信息,请参见 Bug #899424。
会,所有使用 SQL 数据类型的 oracle.sql.*
类均可序列化。
是,Oracle JDBC 驱动程序支持对象和集合,这一特性最早在 8.1.5 版本引入。
用于批量调用的 WaitOption 和 AutoRollback 回滚选项已过时,已无法使用。您无法再使用以下方法:
public void setAutoRollback (int autoRollback); public int getAutoRollback(); public void setWaitOption(int waitOption); public int getWaitOption();
可以,请使用 Thin 服务器驱动程序,8.1.6sdk 及更高版本均支持这一特性。
目前已知的唯一变通方法是将第一个服务器配置为使用 DBLINK 来连接第二个服务器。这能够使 JDBC 驱动程序认为它仍在同一实例中运行并使用 DBLINK 处理详细信息。不过,在 MTS 服务器上使用 DBLINK 可能会出现问题。
这要视具体情况而定,对于某些应用 Thin 驱动程序速度更快,对于另一些应用 OCI 驱动程序速度更快。自 10.1.0 起,Thin 驱动程序可能比 OCI 驱动程序稍快一点。不过,在客户端和服务器使用相同类型的硬件和操作系统的情况下,虽然 Thin 驱动程序速度更快,但 OCI 驱动程序下 RDBMS 的负载会更低一些。总而言之,两者之前的差异很小,不到 10%。现实中,我们的大多数客户都使用 Thin 驱动程序,因为它更易于管理。请您按照您自己的需求来选择。
如果仅执行一次 SQL,Statement 的速度可能会稍快一些。当需要执行多次 SQL 时,PreparedStatement 的速度则快得多。如果您使用语句缓存(我们建议您使用缓存),从缓存获取语句与执行该语句的速度相同。
一般情况下,我们强烈建议您使用 PreparedStatement,尤其是当您需要使用 SQL 向用户发送数据时。通过将数据绑定到 PreparedStatement 参数,您可以防止绝大多数 SQL 注入攻击。与这相比,Statement 的任何优势都可以忽略不计。
首先,您必须使用包含日志记录代码的 Jar 文件。JDBC 驱动程序 ojdbc8.jar 不包含任何日志记录代码,非调试 DMS Jar 文件 ojdbc8dms.jar 包含部分日志记录代码,调试 Jar 文件 *_g.jar 包含大量的日志记录代码。请确保类路径中没有其他 Oracle JDBC Jar 文件。
第二,您必须打开 Oracle JDBC 日志记录。您可以通过设置系统属性 -Doracle.jdbc.Trace=true 来启用全局日志记录,也可以使用 Oracle JDBC Diagnosibility MBean 以编程方式控制日志记录。
// create name
javax.management.ObjectName name = new javax.management.ObjectName("com.oracle.jdbc:type=diagnosibility,name=*");
// get the MBean server
javax.management.MBeanServer mbs = java.lang.management.ManagementFactory.getPlatformMBeanServer();
// find out if logging is enabled or not
System.out.println("LoggingEnabled = " + mbs.getAttribute(name, "LoggingEnabled"));
// enable logging
mbs.setAttribute(name, new javax.management.Attribute("LoggingEnabled", true));
// disable logging
mbs.setAttribute(name, new javax.management.Attribute("LoggingEnabled", false));
您只需打开日志记录即可获得最小输出。要获得更详细、更有针对性的输出,您必须配置 java.util.logging
。
java.util.logging
,从 Oracle JDBC 获取有用的跟踪输出?JDBC 代码创建了大量的 Logger。为了获得有效输出,您需要对每个 Logger 设置日志级别 (logLevel),并在某些位置添加 Handler。有关详细信息,请参阅 JavaDoc 中的 java.util.logging
内容。
或者,您也可以使用 Oracle JDBC 驱动程序安装中的 demo.zip
文件提供的便捷属性文件 OracleLog.properties
。便捷属性文件中的注释详细解释了它的使用方法。这种方法更简单,我们强烈建议您使用。
注意,无论在哪种情况下,您都必须启用日志记录才能获得跟踪输出。您可以随时打开和关闭跟踪输出,且无需重新配置 Logger。Diagnosibility MBean 完全不会与 Logger 冲突。如果您不希望更改源来调用 MBean,您可以将 -Doracle.jdbc.Trace=true
添加到 Java 执行命令中,从而记录整个执行。
有关配置 JDBC 日志记录的更多信息,请参阅关于 JDBC 日志记录的白皮书。请注意,将 Level 设置为 INFO 将记录执行的 SQL,设置为 FINE 将记录所有公共方法的进入和退出,设置为除 FINE 以外的任意值将导致您的整个磁盘空间被日志文件填充。请特别注意这几点。
对于服务器端内部驱动程序,您可以使用 java.util.logging
来获取跟踪输出。您可以使用便捷
OracleLog.properties 文件,方法是执行
System.setProperty("java.util.logging.config.file", "OracleLog.properties")
将 OracleLog.properties
置入 $ORACLE_HOME
。
注:为免疑义,本网页所用以下术语专指以下含义: