探讨JDBC 4.0在设计和性能方面的改进
发布时间:2006-08-24 11:26:51 来源:天极开发 网友评论 0 条 五、 有关RowId方面的改进
在许多数据库中,RowId都被用作唯一标识一个表中行的方法。在查询条件中使用RowId往往是检索数据的最快方法,特别是在Oracle和DB2数据库情况下。现在,既然java.sql.RowId是一种内嵌的Java类型;那么,你就可以充分利用与其用法相关的性能优点。当表中存在重复的数据并且一些行数据相同时,RowId是标识唯一行的最有效的方法。然而,还要注意到,RowId在一个表中是唯一的,而对于整个数据库来说并非如此;它们可能发生变化并且不为所有数据库所支持。典型情况下,RowId不是跨数据源可移植的;因此,当使用多种数据源时应该慎重。
在数据源定义的生命周期内,只要一行未被删除,那么该行相应的RowId就一直保持有效。我们可以调用DatabaseMetadata.getRowIdLifetime()方法来决定RowId的生命周期。这个方法的返回类型是一个枚举类型。现在,把所有这些枚举类型总结到如下的表格中。
其中,只要没有删除行,那么ROWID_VALID_TRANSACTION,ROWID_VALID_SESSION和ROWID_VALID_FOREVER都定义为true。还要注意的是,如果一个行被删除和重新插入,那么RowId会被重新调整(这有可能在数据源中透明实现)。作为一个例子,在Oracle中,如果在一个分区表上设置"enable row movement"语句,并且分区键的一个更新导致该行从一个分区移动到另一个分区,那么RowId将改变。即使在没有设置"enable row movement"标志并且"alter table table_name"发生改变时,RowId也能够改变。
ResultSet和CallableStatement接口都被更新-都包括了一个返回javax.sql.RowId类型的方法getRowID()。
列表3展示了如何从一个ResultSet和CallableStatement中检索RowId。
列表3.得到RowId
在此,RowId可以用于唯一地参考一行并因此可被用于检索或更新行数据。当使用RowId参考来存取或更新数据时,理解生命周期的有效性是十分重要的,从而保证结果的连续性。另外,我还建议你同时使用另一个参考,例如主键,以避免在能够透明地改变RowId的情况下出现不连续的结果。
RowId值还可以被设置或更新。在一种可更新的ResultSet情况下,可以针对表中的一个特定的行使用updateRowId()方法来更新RowId。
另外,PreparedStatement和CallableStatement接口都支持setRowId()方法(其形式不一样),该方法把RowId设置为一个参数值。这个值可以用于针对表中的一个特定的行来参考数据行或更新RowId值。
由上面可知,开发者可以非常容易地设置或更新RowId;这为控制唯一的行标识符并为使这些标识符具有跨表唯一性提供了极大的灵活性。也许,跨表支持的数据源的RowId的可移植性还能够通过在这些数据源间显式地设置一致值来实现。然而,因为系统生成的RowId经常是有效的,并且可以通过透明的操作来改变RowId;所以,最好在一个应用程序中把它们用作只读属性。
六、 利用非标准供应商实现的资源
新型的JDBC API中定义了一个java.sql.Wrapper接口。通过检索代理实例并使用相应的包装代理实例,这个接口提供了存取数据源供应商特定资源的能力。
这个包装接口拥有17个子接口,并且包括Connection,ResultSet,Statement,CallableStatement,PreparedStatement,DataSource,DatabaseMetaData和ResultSetMetaData,等等。这是一种优秀的设计,因为它方便了在创建查询和"结果-设置-检索"生命周期的几乎每一个阶段使用数据源供应商特定的资源。
unwrap()方法返回实现给定接口的对象,从而允许存取供应商特定的方法。isWrapperFor()方法返回一个Boolean值-如果它实现了该接口则返回true;或者,它也有可能直接或间接地成为对象的一个包装类。
作为一个例子,当使用Oracle时,Oracle JDBC驱动程序提供了更新批扩展-与标准JDBC批更新机制相比,它具有更好的性能且更为有效。对于早期的JDBC版本来说,这意味着要在代码中使用Oracle特定的定义,例如OraclePreparedStatement。这样以来就减弱了代码的可移植性。而借助于现在新型的API,许多前面这些有效的实现都能够被包装和被暴露在标准JDBC定义中。
七、 针对驱动程序加载的服务提供者机制
在JDBC 4.0以前,在一种非托管的或独立的程序中,你必须显式地通过调用Class.forName方法来加载JDBC驱动器类,如列表4所示:
列表4.Class.forName方法
借助于JDBC 4.0,如果JDBC驱动程序供应商把他们的驱动程序打包为服务(在服务提供者机制下定义为每一种JAR规范),那么DriverManager代码将通过在classpath中搜索它来隐式地装载该驱动程序。这种机制的优点在于,开发者不需要了解这种特定的驱动程序类,并且能够使用JDBC来编写较少的代码实现。另外,既然驱动程序类名不再存在于代码中,那么只改变一个名字并不要求重新编译。如果在classpath中指定了多个驱动程序,那么DriverManger将试图使用它在classpath中所找到的第一个驱动程序来创建一种连接,并且在需要时能够继续遍历下一个驱动程序。
八、 结论
在本文中,我们一同探讨了JDBC 4.0的一些新的和改进的特征。从中可以看出,许多新特征进一步便利了开发,从而提高了开发者的生产效率。另一方面,该规范并没有消除对于其它JDBC框架提供的模板化工具和高级异常处理能力的使用。然而,对该规范也存在一些批评。例如,一些人认为注释的使用会导致在代码中硬编码(而这往往导致在代码维护阶段出现问题)。究其实效,还有待于实践检验。
在许多数据库中,RowId都被用作唯一标识一个表中行的方法。在查询条件中使用RowId往往是检索数据的最快方法,特别是在Oracle和DB2数据库情况下。现在,既然java.sql.RowId是一种内嵌的Java类型;那么,你就可以充分利用与其用法相关的性能优点。当表中存在重复的数据并且一些行数据相同时,RowId是标识唯一行的最有效的方法。然而,还要注意到,RowId在一个表中是唯一的,而对于整个数据库来说并非如此;它们可能发生变化并且不为所有数据库所支持。典型情况下,RowId不是跨数据源可移植的;因此,当使用多种数据源时应该慎重。
在数据源定义的生命周期内,只要一行未被删除,那么该行相应的RowId就一直保持有效。我们可以调用DatabaseMetadata.getRowIdLifetime()方法来决定RowId的生命周期。这个方法的返回类型是一个枚举类型。现在,把所有这些枚举类型总结到如下的表格中。
| RowIdLifetime枚举类型 | 定义 |
| ROWID_UNSUPPORTED | 数据源不支持RowId类型 |
| ROWID_VALID_OTHER | 实现依赖的生命周期 |
| ROWID_VALID_TRANSACTION | 生命周期至少包含事务 |
| ROWID_VALID_SESSION | 生命周期至少包含会话 |
| ROWID_VALID_FOREVER | 无限制生命周期 |
其中,只要没有删除行,那么ROWID_VALID_TRANSACTION,ROWID_VALID_SESSION和ROWID_VALID_FOREVER都定义为true。还要注意的是,如果一个行被删除和重新插入,那么RowId会被重新调整(这有可能在数据源中透明实现)。作为一个例子,在Oracle中,如果在一个分区表上设置"enable row movement"语句,并且分区键的一个更新导致该行从一个分区移动到另一个分区,那么RowId将改变。即使在没有设置"enable row movement"标志并且"alter table table_name"发生改变时,RowId也能够改变。
ResultSet和CallableStatement接口都被更新-都包括了一个返回javax.sql.RowId类型的方法getRowID()。
列表3展示了如何从一个ResultSet和CallableStatement中检索RowId。
列表3.得到RowId
| //从一个ResultSet检索RowId的方法签名: RowId getRowId (int columnIndex) RowId getRowId (String columnName) ... Statement stmt = con.createStatement (); ResultSet rs = stmt. ExecuteQuery (…); while (rs.next ()) { ... java.sql.RowId rid = rs.getRowId (1); ... } //从一个CallableStatement检索RowId的方法签名: RowId getRowId (int parameterIndex) RowId getRowId (String parameterName) Connection con; ... CallableStatement cstmt = con.prepareCall (…); ... cstmt.registerOutParameter (2, Types.ROWID); ... cstmt.executeUpdate (); ... java.sql.RowId rid = cstmt.getRowId (2); |
在此,RowId可以用于唯一地参考一行并因此可被用于检索或更新行数据。当使用RowId参考来存取或更新数据时,理解生命周期的有效性是十分重要的,从而保证结果的连续性。另外,我还建议你同时使用另一个参考,例如主键,以避免在能够透明地改变RowId的情况下出现不连续的结果。
RowId值还可以被设置或更新。在一种可更新的ResultSet情况下,可以针对表中的一个特定的行使用updateRowId()方法来更新RowId。
另外,PreparedStatement和CallableStatement接口都支持setRowId()方法(其形式不一样),该方法把RowId设置为一个参数值。这个值可以用于针对表中的一个特定的行来参考数据行或更新RowId值。
由上面可知,开发者可以非常容易地设置或更新RowId;这为控制唯一的行标识符并为使这些标识符具有跨表唯一性提供了极大的灵活性。也许,跨表支持的数据源的RowId的可移植性还能够通过在这些数据源间显式地设置一致值来实现。然而,因为系统生成的RowId经常是有效的,并且可以通过透明的操作来改变RowId;所以,最好在一个应用程序中把它们用作只读属性。
六、 利用非标准供应商实现的资源
新型的JDBC API中定义了一个java.sql.Wrapper接口。通过检索代理实例并使用相应的包装代理实例,这个接口提供了存取数据源供应商特定资源的能力。
这个包装接口拥有17个子接口,并且包括Connection,ResultSet,Statement,CallableStatement,PreparedStatement,DataSource,DatabaseMetaData和ResultSetMetaData,等等。这是一种优秀的设计,因为它方便了在创建查询和"结果-设置-检索"生命周期的几乎每一个阶段使用数据源供应商特定的资源。
unwrap()方法返回实现给定接口的对象,从而允许存取供应商特定的方法。isWrapperFor()方法返回一个Boolean值-如果它实现了该接口则返回true;或者,它也有可能直接或间接地成为对象的一个包装类。
作为一个例子,当使用Oracle时,Oracle JDBC驱动程序提供了更新批扩展-与标准JDBC批更新机制相比,它具有更好的性能且更为有效。对于早期的JDBC版本来说,这意味着要在代码中使用Oracle特定的定义,例如OraclePreparedStatement。这样以来就减弱了代码的可移植性。而借助于现在新型的API,许多前面这些有效的实现都能够被包装和被暴露在标准JDBC定义中。
七、 针对驱动程序加载的服务提供者机制
在JDBC 4.0以前,在一种非托管的或独立的程序中,你必须显式地通过调用Class.forName方法来加载JDBC驱动器类,如列表4所示:
列表4.Class.forName方法
| Class.forName ("com.driverprovider.jdbc.jdbcDriverImpl"); |
借助于JDBC 4.0,如果JDBC驱动程序供应商把他们的驱动程序打包为服务(在服务提供者机制下定义为每一种JAR规范),那么DriverManager代码将通过在classpath中搜索它来隐式地装载该驱动程序。这种机制的优点在于,开发者不需要了解这种特定的驱动程序类,并且能够使用JDBC来编写较少的代码实现。另外,既然驱动程序类名不再存在于代码中,那么只改变一个名字并不要求重新编译。如果在classpath中指定了多个驱动程序,那么DriverManger将试图使用它在classpath中所找到的第一个驱动程序来创建一种连接,并且在需要时能够继续遍历下一个驱动程序。
八、 结论
在本文中,我们一同探讨了JDBC 4.0的一些新的和改进的特征。从中可以看出,许多新特征进一步便利了开发,从而提高了开发者的生产效率。另一方面,该规范并没有消除对于其它JDBC框架提供的模板化工具和高级异常处理能力的使用。然而,对该规范也存在一些批评。例如,一些人认为注释的使用会导致在代码中硬编码(而这往往导致在代码维护阶段出现问题)。究其实效,还有待于实践检验。
- 推荐阅讯
- 基于Ajax的应用程序架构设计汇总
- 开源软件在2006年如何走过?
- 关于Web 2.0 网站的创业思考
- Web2.0开始试探钱途 视频广告逐渐增多
- WEB2.0教程:什么是SNS网站?
- VS2005中使用强类型DataSet简化开发
- EMC与微软共推在微软应用环境中的ILM解决方
- 开源Eclipse风头正劲 Sun态度若明若暗
- 雅虎发布自助构建网站应用编程接口
- 玩玩Spring之Rod Johnson与轮子理论
- 阅读排行
- 1..net页面间的参数传递简单实例
- 2.VC++与Matlab混合编程之引擎操作详解
- 3.Oracle数据库数据对象分析
- 4.Eclipse3.2+Tomcat5.5.17+Oracle9配置
- 5.Oracle数据库中索引的维护
- 6.在Oracle的网络结构中解决连接问题
- 7.Oracle数据安全面面观
- 8.Oracle数据库的ORA-00257故障解决过程
- 9.Oracle数据库备份与恢复的三种方法
- 10.Oracle与SQL Server在企业应用中的比较
- 专题教程
- Windows Server-Windows Server文档-Windows Server新闻-Windows Ser PostgreSQL-PostgreSQL文档-PostgreSQL新闻-PostgreSQL专家
- WebLogic-WebLogic文档-WebLogic新闻-WebLogic专家 FreeBSD-FreeBSD文档-FreeBSD新闻-FreeBSD专家
- Linux-内核 GUI KDE Gnome DNS FTP 安全 安装-Linux专区 Windows-AD IIS ServerCore 虚拟化 安全 HPC-Windows专区
- 大话G游 专题:手机病毒揭密
- ARP攻击防范与解决方案 路由故障处理手册
