JDBC 2.0 API 包括两个package:
1. java.sql 为JDBC 2.0的核心包,其中包括了JDBC 1.0规范中规定的API和新的核心API,这个包包含于Java 2 Standard Edition中.
2. javax.sql 为JDBC 2.0的标准扩展包,相对与JDBC 1.0而言是全新的,这个包包含于Java 2 Enterprise Edition中.
★ 采用了新的方法连接数据库 DataSource Interface
JDBC 2.0 提供了新的接口DataSource用来实现数据库连接,可以替代1.0中提供的DriverManager类。好处是:
☆ 增强了代码的可移植性
☆ 方便了代码的维护
一个DataSource对象代表一个实际的数据源。这个数据源可以是从关系数据库到表格形式的文件,完全依赖于它是怎样实现的.一个数据源对象注册到JNDI名字服务后,应用程序就可以从JNDI服务器上取得该对象,并使用之和数据源建立连接.
数据源及如何装入的信息(名字,地址,端口等等)以Properties的形式保存在DataSource对象中.这样就增强了应用程序的可移植性,因为程序中不需要像使用DriverManager那样给出硬性的驱动器名字(往往包含了特定厂商的名字). 这种做法还增强了代码的可维护性,比如数据源移植到另一台服务器上后, 所需要作的就是更新一下相关的property,使用数据源的代码更不不必改动.
系统管理员或者有相应权限的人实现DataSource对象. DataSource对象的实现需要设置对象的properties并把它注册到JNDI名字服务器上, 这些活动可能会用特定工具来实现. 系统管理员用一个逻辑名字对应DataSource对象,这个名字可是是任意的. 在下面的例子中DataSource对象的名字是InventoryDB. 依照传统习惯, DataSource对象的名字包含在jdbc下, 所以这个数据源对象的完整名字是:jdbc/InventoryDB.
实现数据源对象后, 应用程序员就可以使用它来建立和数据源之间的连接了. 下面的代码片断演示了通过这种方式获得连接. 上面两行使用了JNDI API获得DataSource对象,第三行代码使用JDBC API获得连接:
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("jdbc/InventoryDB"):
Connection conn = ds.getConnection("password","username");
DataSource对象中获得的的Connection对象和用DriverManager.getConnection方法获得的对象是等同的. 由于DataSource方法的优点, 该方法成为获得连接的推荐方法. 所有基于JDBC 2.0的驱动器应该会包含DataSource接口的实现以及javax.sql包.
对普通程序员而言, DataSource对象方法只是一种选择. 如果要使用连接缓冲池(Connection pooling)或者分布式交换, 则必须使用DataSource对象获得连接.原因在下文中阐述.
★ Connection Pooling
连接缓冲池是这样工作的:当一个应用程序关闭一个连接时, 这个连接并不真正释放而是被循环利用.因为建立连接是消耗较大的操作, 循环利用连接可以显著的提高性能,因为可以减少新连接的建立.
比如一个应用程序需要连接一个由名字是EmployeeDB的DataSource对象代表的数据源, 通过缓冲池获得连接的代码演示如下:
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("jdbc/EmloyeeDB");
Connection con = ds.getConnection("password","username");
因为连接的数据源不同所以和上面的例子中的名字不一样. DataSource.getConnction方法返回的连接是否被缓存完全依赖于该DataSource对象的实现方式. 如果它将用于支持连接缓冲的中间层服务器(Middle Tier Server), 则DataSource对象将自动返回将被缓存、循环利用的连接.
基本上不需要改变任何代码就可以获得缓冲池连接. 唯一需要注意的就是(我们已经这样做了:P),需要在finally块中释放连接,这应该是释放所有连接的较好方法.这样, 即使抛出了异常, 连接也会还给连接缓冲池:
finally{
if(con != null) con.close();
}
finally块保证了连接的循环利用.
★ Distributed Transactions(分布式交换)
获得用于分布式交换的情形类似于获得缓冲池连接. 差别仍然是DataSource对象的实现方式, 而不是获得连接程序代码的不同.
假定DataSource类被实现为用于中间件的分布式交换设施,下面的代码将获得用于分布式交换的连接:
Context ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("jdbc/EmloyeeDB");
Connection con = ds.getConnection("password","username");
出于性能的考虑, 用于获得分布式交换的连接的DataSource对象差不多总是会同时实现缓冲池连接.
从程序员的角度来看, 获得普通连接和获得用于分布式交换的连接之间没有区别. 唯一的不同是交换界限(什么时候开始,什么时候结束)由交换管理器在后台处理. 应用程序不应该做任何妨碍交换管理器的事情. 所以程序不能直接调用commit或者rollback方法, 不能设置auto-commit模式.
下面几行代码中con是可用于分布式交换的Connection对象, 演示了在con参与分布式交换是不能作的事情:
con.commit();
or
con.rollback();
or
con.setAutoCommit(true);
普通连接默认打开auto-commit模式. 用于分布式交换的连接对象默认关闭auto-commit模式. 应注意的是用于分布式交换的连接也可以用于非分布式交换模式, 交换边界的限制仅在连接是分布式交换一部分是有效.
实现支持连接缓冲池的DataSource对象,需要实现ConnectionPoolDataSource对象, 三层构架的中间件的连接缓冲模块将会使用它. 同样, 实现支持分布式交换的DataSource对象也需要实现XADataSource对象, 中间件的分布式交换构件会使用该对象.
ConnectionPoolDataSource和XADataSource对象对程序员而言是完全透明的, 应有驱动程序厂商提供.
★ Rowsets
RowSet对象是一系列rows的容器. 根据不通的目的,可以通过多种方式实现. RowSet接口和其相关接口与JDBC 2.0标准扩展的其他部分的差别是它们不是驱动程序实现的一部分. RowSet对象在驱动程序的上层实现,可以被任何人实现.
任何rowset类型都要实现RowSet接口(继承了ResultSet接口). 所以RowSet对象拥有ResultSet对象的所有功能:可以用getXXX方法取值,用updateXXX方法更新, 移动游标, 执行其他相关任务.
当然rowset也有其新功能.作为JavaBeans组件, RowSet对象提供了方法监听属性的get/set.其中一个属性是command串,这个属性往往是一个查询,RowSet接口提供可设置command属性和执行之的方法. 这意味这RowSet对象能够执行自己的检索命令用查询结果填充自己的内容. 或者RowSet对象可以实现用来使用任何表格式的数据源填充自己, 而不是局限于关系数据库.
从数据源取得数据后, RowSet对象可以断开于数据源的连接,这使得该对象很小(如果数据量特别不大). rowset也可以序列化. 所以rowset很小并可以序列化, 一个断开连接的rowset是传送数据给瘦客户机的理想工具.
rowset可以被更新,然后重新连接数据源以传送更新的值. 如果设置了监听者, 当rowset中的游标被移动和内容变化时,会通知监听者.
如, 图形界面组件(如条图)可以被注册为监听者,当rowset上有事件发生将会同志它, 它可以重画自身反映变化.
RowSet接口可以有多种实现方式, 依赖于你想做什么.Sun提供了实现的例子CachedRowSet:
http://developer.java.sun.com/developer/earlyAccess/crs/index.html
如果您想测试DataSource,一种较为方便的方法是使用支持JDBC2.0和JNDI的Application Server,如Jrun, 如果你已经安装了Jrun,则可以到JMC中配置DataSource了,请看Jrun手册学习使用DataSource的方法。