请参见:
描述
接口摘要 | |
---|---|
SyncResolver | 定义一个框架,当发生同步冲突时,它允许应用程序使用手工决策树来确定应该执行的操作。 |
TransactionalWriter | 一个专用接口,用来方便地扩展标准 SyncProvider 抽象类以便拥有细粒度的事务控制。 |
XmlReader | 一个专用接口,用来方便地扩展 SyncProvider 抽象类以用于面向 XML 的同步提供者。 |
XmlWriter | 一个专用接口,用来方便地扩展 SyncProvider 抽象类以用于面向 XML 的同步提供者。 |
类摘要 | |
---|---|
SyncFactory | 该服务提供者接口 (SPI) 机制可以生成由非连接 RowSet 对象使用的 SyncProvider 实例。 |
SyncProvider | 为非连接 RowSet 对象提供 reader/writer 功能的同步机制。 |
异常摘要 | |
---|---|
SyncFactoryException | 指示 SyncFactory 机制发生的错误。 |
SyncProviderException | 指示 SyncProvider 机制发生的错误。 |
第三方供应商在其同步提供者的实现中必须使用的标准类和接口。这些类和接口被称为服务提供者接口 (SPI)。供应商通过向 jdbc@sun.com
发送电子邮件,可以使其实现被 JDBC 网页所包含,该网页列出了可用的 SyncProvider
实现。这样做有助于开发人员了解该实现。为了使 RowSet
对象能够使用实现,供应商必须向 SyncFactory
单件注册。(有关注册过程和所使用命名约定的完整解释,请参阅 SyncProvider
的类注释。)
以下类和接口组成了 javax.sql.rowset.spi
包:
SyncFactory
SyncProvider
SyncFactoryException
SyncProviderException
SyncResolver
XmlReader
XmlWriter
TransactionalWriter
javax.sql
包中的以下接口也是 SPI 的一部分:
RowSetReader
RowSetWriter
SyncProvider
实现通过以下机制提供非连接 RowSet
对象:将数据读入该对象和将在该对象中修改的数据写回底层数据源。当调用 CachedRowSet
方法 execute
或 populate
时,reader、RowSetReader
或 XMLReader
对象可以将数据读入 RowSet
对象。当调用 CachedRowSet
方法 acceptChanges
时,writer、RowSetWriter
或 XMLWriter
对象可以将更改写回底层数据源。
将 RowSet
对象中的更改写入其数据源的过程称为同步。RowSet
正在使用的 SyncProvider
实现可以确定 RowSet
对象的 writer 所使用的同步级别。同步的各种级别被称为等级。
同步的较低等级称为乐观 并发级别,因为它们乐观地假设不存在任何冲突或仅有极少的冲突。当在 RowSet
对象中修改的同一数据也在数据源中修改时,会发生冲突。使用乐观并发模型意味着如果存在冲突,则会丢失对数据源或 RowSet
对象的修改。
同步的较高等级被称为悲观,因为它们假设数据源会被访问并修改。这些等级可以设置各种级别的锁定以增加不发生冲突的几率。
最低级别的同步只将对 RowSet
对象进行的任何更改写入到其底层数据源。writer 不执行任何检查冲突的操作。如果存在冲突,并且数据源值被重写,则其他方对数据源进行的更改会丢失。
RIXMLProvider
实现使用最低级别的同步,并仅将 RowSet
更改写入数据源。确实是这样,因为 XML 数据源通常不会启用事务处理技术来维护数据完整性。但是,特定的标准化组织已经在考虑提供基于 XML 的同步。有关详细信息,请参阅
http://www.syncml.org
对于下一个级别,writer 会查看是否存在冲突,如果存在,则它不将任何内容写入到数据源。此并发级别的问题是如果另一方在 RowSet
对象获得其数据后修改了数据源中相应数据,则对 RowSet
对象进行的修改会丢失。RIOptimisticProvider
实现使用此级别的同步。
对于称为悲观并发的较高级别的同步,writer 会采取一些步骤(如设置锁定)来避免冲突。设置锁定可以是在一个行上设置,也可以是在一个表或整个数据源上设置。因此,同步级别是一个以下两者间的权衡:用户并发访问数据源的能力和 writer 保持 RowSet
对象及其同步数据源中数据的能力。
它要求所有非连接 RowSet
对象(CachedRowSet
、FilteredRowSet
、JoinRowSet
和 WebRowSet
对象)从 SyncFactory
机制获取它们的 SyncProvider
对象。
参考实现 (RI) 提供两个同步提供者。
SyncFactory
实例将它提供给非连接 RowSet
对象。RowSet
对象和数据源同步之前是否存在冲突。如果存在冲突,它不执行任何操作,这意味着对 RowSet
对象的更改不会保留到数据源。 WebRowSet
对象一起使用的同步提供者,它是一个以 XML 格式写入或以 XML 格式进行读取的 rowset。RIXMLProvider
实现根本不检查任何冲突,仅将 WebRowSet
对象中的任何更新数据写入底层数据源。WebRowSet
对象处理 XML 数据时使用此提供者。 SyncProvider
实现与参考实现捆绑在一起,使它们总是可用于
RowSet
实现。
SyncProvider
实现通过向单一
SyncFactory
注册使它们本身可用。当
RowSet
对象通过在构造方法中指定某个提供者,或者指定它作为
CachedRowSet
方法
setSyncProvider
的参数来请求该提供者时,该单一
SyncFactory
会查看请求的提供者是否已向它注册。如果已注册,则
SyncFactory
创建一个它的实例,并将它传递到发出请求的
RowSet
对象。如果指定的
SyncProvider
实现没有注册,则单一
SyncFactory
导致抛出
SyncFactoryException
对象。如果不指定任何提供者,则单一
SyncFactory
将创建一个默认的提供者实现
RIOptimisticProvider
的实例,并将它传递到发出请求的
RowSet
对象。
如果 WebRowSet
对象在其构造方法中未指定提供者,则 SyncFactory
将为它提供一个 RIOptimisticProvider
实例。但是,可以实现 WebRowSet
的构造方法来将提供者设置为 RIXMLProvider
,它以 XML 格式读取和写入 RowSet
对象。
有关更多详细信息,请参阅 SyncProvider 类规范。
供应商可以使用任何一个可能级别的同步开发 SyncProvider 实现,从而给 RowSet
对象一个选择同步机制的机会。供应商通过向 jdbc@sun.com
的 Sun Microsystems 注册完全限定类名称使其实现可用。下面将更加详细地讨论此过程。
服务提供者接口提供了一个可插入的机制,通过该机制可以注册 SyncProvider
实现,然后在需要时可生成该实现。SyncFactory
使用的延时引用机制 (lazy reference mechanism) 在非连接 RowSet
对象需要实例之前不会创建实例,从而限制了不必要的资源消耗。SyncFactory
类也提供了标准 API 来配置日志选项和特定的 SyncProvider
实现可以提供的流。
2.2 向 SyncFactory
注册
第三方 SyncProvider
实现必须向 SyncFactory
注册,以便非连接 RowSet
对象获取它,从而使用其 javax.sql.RowSetReader
和 javax.sql.RowSetWriter
实现。以下注册机制可用于所有 SyncProvider
实现:
SyncProvider
对象中。
SyncFactory
提供此上下文,以便机制能正确运行。 关于如何指定系统属性或属性文件中的属性以及如何配置 JNDI 上下文的细节,已在 SyncFactory
类描述中进行了详细说明。
2.3 SyncFactory 提供者实例生成策略
如果正确地注册了提供者,则 SyncFactory
会生成所请求的 SyncProvider
对象。当使用指定的 SyncProvider
实现实例化非连接 RowSet
对象,或者使用替代 SyncProvider
对象在运行时对它进行配置时,请遵循以下策略。
SyncProvider
对象,并且 SyncFactory
不 包含对提供者的任何引用,则抛出一个 SyncFactoryException
。
SyncProvider
对象,并且 SyncFactory
包含对提供者的引用,则提供所请求的提供者。
SyncProvider
对象,则提供参考实现提供者 RIOptimisticProvider
。 在
类中更详细地阐述了这些策略。 SyncFactory
完全可插入到 SyncFactory
的兼容 SyncProvider
实现必须扩展和实现 SyncProvider
类中所有的抽象方法。另外,实现必须确定 SyncProvider
类定义中定义的等级、锁定和可更新视图的功能。必须支持一个或多个 SyncProvider
描述标准。供应商实现需要提供一系列的等级、锁定和可更新视图的功能。
此外,SyncProvider
命名约定必须符合 SyncProvider
类描述中的详细信息。
3.2 等级
JSR 114 定义了一组等级,用来描述 SyncProvider
对象可以提供非连接 RowSet
对象的同步质量。按服务质量从低到高的顺序列出了这些等级。
SyncProvider
实现仅尝试将在 RowSet
对象中更改的任何数据写入底层数据源,重写存在的任何内容。不尝试比较原始值与当前值来查看是否存在冲突。使用此等级实现 RIXMLProvider
。
SyncProvider
实现将检查在上一次同步和当前正进行的同步之间进行更改的行中的冲突。任何原始数据源中已被修改的更改不会反映在非连接 RowSet
对象中。如果不存在任何冲突,则将 RowSet
对象中的更改写入数据源。如果存在冲突,则不写入任何更改。RIOptimisticProvider
实现使用此等级。
SyncProvider
实现将检查所有的行,包括在非连接 RowSet
对象中没有更改的行。因此,当同步成功完成时,对底层数据源中的行进行的任何更改将反映在非连接 RowSet
对象中。
SyncProvider
实现将锁定原始数据源中的行(该行与 RowSet
对象中更改的行对应),以减少其他进程修改数据源中同一数据的可能性。
SyncProvider
实现将锁定用于填充 RowSet
对象的原始查询所影响的整个视图和/或表。 3.3 锁定
JSR 114 定义一个常量集,它指定是否对 RowSet
对象的底层数据源进行了某些锁定,如果是,它还指定进行锁定的构造。当 RowSet
对象从数据源断开时,这些锁定将保留在数据源上。
这些常量应被视为对等级常量的补充。当 RowSet
对象从其数据源断开时,多数等级设置的默认设置要求不保留任何数据源锁定。等级 GRADE_LOCK_WHEN_MODIFIED
和 GRADE_LOCK_WHEN_LOADED
允许非连接 RowSet
对象对锁定程度进行细粒度控制。
RowSet
对象没有其他指示,则这是所有 SyncProvider
实现的默认锁定设置。
RowSet
对象的原始 SQL 查询会涉及这些行。
RowSet
对象的查询会涉及这些表。
RowSet
对象使用的整个数据源进行锁定。 3.4 可更新的视图
使用 SQL VIEW
中的数据可以填充 RowSet
对象。以下常量指示 SyncProvider
对象是否可以更新从中衍生出 VIEW
的表中的数据。
SyncProvider
实现支持对从中衍生出用于填充 RowSet
对象的 SQL VIEW
的表的同步。
SyncProvider
实现不支持对从中衍生出用于填充 RowSet
对象的 SQL VIEW
的表的同步。 3.5 SyncProvider
等级和锁定的用法
在下面的示例中,引用 CachedRowSetImpl 实现通过调用 setSyncProvider 方法重新配置其当前 SyncProvider 对象。
CachedRowSetImpl crs = new CachedRowSetImpl(); crs.setSyncProvider("com.foo.bar.HASyncProvider");应用程序通过非连接
RowSet
对象可以检索当前正在使用的
SyncProvider 对象。它也可以检索实现提供者的同步等级和当前正在使用的锁定程度。另外,应用程序可以灵活地设置要使用的锁定程度,从而增加成功同步的可能性。以下代码片段展示了这些操作。
SyncProvider sync = crs.getSyncProvider();
switch (sync.getProviderGrade()) {
case: SyncProvider.GRADE_CHECK_ALL_AT_COMMIT
//A high grade of optimistic synchronization
break;
case: SyncProvider.GRADE_CHECK_MODIFIED_AT_COMMIT
//A low grade of optimistic synchronization
break;
case: SyncProvider.GRADE_LOCK_WHEN_LOADED
// A pessimistic synchronization grade
break;
case: SyncProvider.GRADE_LOCK_WHEN_MODIFIED
// A pessimistic synchronization grade
break;
case: SyncProvider.GRADE_NONE
// No synchronization with the originating data source provided
break;
}
switch (sync.getDataSourcLock() {
case: SyncProvider.DATASOURCE_DB_LOCK
// A lock is placed on the entire datasource that is used by the
// RowSet
object
break;
case: SyncProvider.DATASOURCE_NO_LOCK
// No locks remain on the originating data source.
break;
case: SyncProvider.DATASOURCE_ROW_LOCK
// A lock is placed on the rows that are touched by the original
// SQL statement used to populate
// the RowSet object that is using the SyncProvider
break;
case: DATASOURCE_TABLE_LOCK
// A lock is placed on all tables that are touched by the original
// SQL statement used to populated
// the RowSet object that is using the SyncProvider
break;
使用
SyncFactory
类中的静态实用工具方法也能够确定当前向
SyncFactory
注册的
SyncProvider
实现所组成的列表。
Enumeration e = SyncFactory.getRegisteredProviders();
SyncResolver
提供了一种应用程序手动确定发生冲突时应执行的操作的方式。当 CachedRowSet
方法 acceptChanges
完成并检测到一个或多个冲突时,它将抛出一个 SyncProviderException
对象。应用程序可以捕获该异常,并通过调用方法 SyncProviderException.getSyncResolver()
使它检索 SyncResolver
对象。 SyncResolver
对象是实现了 SyncResolver
接口的一种特殊 CachedRowSet
对象或 JdbcRowSet
对象,它逐行检查冲突。它与同步的 RowSet
对象完全相同,区别在于它仅包含数据源中导致冲突的数据。将所有其他列值都设置为 null
。为了从一个冲突值导航到另一个冲突值,SyncResolver
对象提供了方法 nextConflict
和 previousConflict
。
SyncResolver
接口也提供了一些方法,用于执行以下操作:
RowSet
对象中的值(如果它需要更改) 在调用 CachedRowSet
方法 acceptChanges
时,它会委托给 RowSet
对象的 SyncProvider
对象。实现的 SyncProvider
对象提供 writer 的方式决定对冲突执行检查的级别(等级)。完成所有的冲突检查并且找到一个或多个冲突之后,方法 acceptChanges
会抛出一个 SyncProviderException
对象。应用程序可以捕获该异常,并使用该异常获取 SyncResolver
对象。
然后,应用程序可以使用 SyncResolver
方法获取关于每个冲突的信息,并决定要执行的操作。如果应用程序逻辑或用户决定 RowSet
对象中的值应该保留,那么应用程序或用户可以使用它重写数据源值。