Module  java.sql.rowset

Package javax.sql.rowset.spi

第三方供应商在实施同步提供程序时必须使用的标准类和接口。 这些类和接口被称为服务提供者接口(SPI)。 为了使RowSet对象能够使用实现,供应商必须使用SyncFactory单例注册它。 (有关注册过程和使用的命名约定的完整说明,请参阅SyncProvider的类注释。)

目录

1.0 Package Specification

以下类和接口组成了javax.sql.rowset.spi软件包:

  • SyncFactory
  • SyncProvider
  • SyncFactoryException
  • SyncProviderException
  • SyncResolver
  • XmlReader
  • XmlWriter
  • TransactionalWriter
以下接口在javax.sql包中也是SPI的一部分:
  • RowSetReader
  • RowSetWriter

一个SyncProvider实现提供了一个断开连接的RowSet对象,具有读取数据的机制,并将已经修改的数据写入底层数据源。 读者RowSetReaderXMLReader对象,当CachedRowSet方法executepopulate时,将数据读入RowSet对象。 作者 ,一个RowSetWriterXMLWriter对象,当调用CachedRowSet方法acceptChanges时, CachedRowSet acceptChanges回底层数据源。

RowSet对象中的更改写入其数据源的过程称为同步 RowSet对象正在使用的SyncProvider实现决定了RowSet对象的作者使用的同步级别。 各种级别的同步被称为等级

较低等级的同步被称为乐观并发级别,因为它们乐观地假设不会有冲突或很少的冲突。 当在数据源中修改了RowSet对象中修改的相同数据时,存在冲突。 使用乐观并发模型意味着如果存在冲突,则会丢失对数据源或RowSet对象的修改。

更高等级的同步被称为悲观,因为他们假设其他人将访问数据源并进行修改。 这些等级设置不同级别的锁以增加没有发生冲突的机会。

最低级别的同步只是将对RowSet对象的任何更改写入其底层数据源。 作家什么也不做任何检查冲突。 如果存在冲突并且数据源值被覆盖,则其他方对数据源所做的更改将丢失。

RIXMLProvider实现使用最低级别的同步,只是将RowSet更改写入数据源。

对于下一个级别,作者检查是否存在任何冲突,如果有的话,它不会对数据源写任何内容。 这种并发级别的问题是,如果另一方已经修改了数据源中的相应数据,因为RowSet对象获得了其数据,则对RowSet对象所做的更改将丢失。 RIOptimisticProvider实现使用这种级别的同步。

在较高级别的同步,称为悲观并发,作者采取措施通过设置锁来避免冲突。 设置锁可以从设置单个行的锁定到在表或整个数据源上设置锁定而有所不同。 因此,同步级别是用户同时访问数据源的能力与作者将数据保持在RowSet对象及其数据源同步的能力之间的折衷。

这是所有断开的要求RowSet对象( CachedRowSetFilteredRowSetJoinRowSet ,并WebRowSet对象)获得其SyncProvider从对象SyncFactory机制。

参考实现(RI)提供了两个同步提供程序。

  • RIOptimisticProvider
    当未指定提供程序实现时, SyncFactory实例将提供给断开连接的RowSet对象的默认提供程序。
    该同步提供程序使用乐观并发模型,假设在数据库中访问相同数据的用户之间将存在很少的冲突。 它避免使用锁; 而是在尝试同步RowSet对象和数据源之前检查是否存在冲突。 如果有冲突,它什么都不做,这意味着对RowSet对象的更改不会持久RowSet到数据源。
  • RIXMLProvider
    可与WebRowSet对象一起使用的同步提供程序,该对象是可以以XML格式编写或从XML格式读取的行。 RIXMLProvider实现不会检查冲突,只需将WebRowSet对象中的任何更新数据写入基础数据源。 WebRowSet对象在处理XML数据时使用此提供程序。
这些SyncProvider实现与参考实现捆绑在一起,这使得它们始终可用于RowSet实现。 SyncProvider实现使自己可以通过注册SyncFactory单例。 当一个RowSet对象请求一个提供者时,通过在构造函数中指定它或作为CachedRowSet方法setSyncProvider的参数, SyncFactory单例检查以查看请求的提供者是否已经注册。 如果它有, SyncFactory创建一个实例,并将其传递给请求的RowSet对象。 如果指定的SyncProvider实现尚未注册,则SyncFactorySyncFactory导致抛出SyncFactoryException对象。 如果没有指定提供者,则SyncFactory单例将创建默认提供程序实现的实例RIOptimisticProvider ,并将其传递给请求的RowSet对象。

如果一个WebRowSet对象在其构造函数中未指定提供者,那么SyncFactory将给它一个RIOptimisticProvider的实例。 但是,实现了WebRowSet的构造函数来将提供程序设置为RIXMLProvider ,它以XML格式读写RowSet对象。

有关详细信息,请参阅SyncProvider类规范。

供应商可以利用任何一个可能的同步级别来开发一个SyncProvider实现,从而为RowSet对象提供同步机制的选择。

2.0 Service Provider Interface Architecture

2.1概述

服务提供商接口提供可插拔机制,通过该机制可以注册SyncProvider实现,然后在需要时生成。 SyncFactory采用的延迟引用机制通过SyncFactory创建实例SyncFactory限制不必要的资源消耗,直到被断开的RowSet对象需要。 SyncFactory类还提供了一个标准API来配置可能由特定的SyncProvider实现提供的日志记录选项和流。

2.2注册SyncFactory

第三方SyncProvider实施必须与注册SyncFactory为了断开连接RowSet对象获取它,从而使用其javax.sql.RowSetReaderjavax.sql.RowSetWriter实现。 以下注册机制适用于所有SyncProvider实现:

  • 系统属性 - 在命令行中设置的属性。 这些属性是在运行时设置的,并且每次调用Java应用程序时都将应用于系统范围。 详见"Related Documentation"相关资料。
  • 属性文件 - 在标准属性文件中指定的属性。 这可以使用系统属性或通过修改位于平台运行时的标准属性文件来指定。 该技术的参考实现包括可编辑的标准属性文件,以添加其他SyncProvider对象。
  • JNDI上下文 - 可以在JNDI上下文中注册可用的提供者。 SyncFactory将尝试加载绑定到上下文的SyncProvider对象,并将其注册到工厂。 必须将此上下文提供给SyncFactory才能正常运行的机制。

有关如何指定属性文件中的系统属性或属性以及如何配置JNDI上下文的详细信息,请参见SyncFactory类描述。

2.3 SyncFactory Provider实例生成策略

如果提供程序已正确注册,则SyncFactory生成请求的SyncProvider对象。 当使用指定的SyncProvider实现来实例化断开连接的RowSet对象时,或者在运行时使用替代的SyncProvider对象重新配置,则遵守以下策略。

  • 如果SyncProvider指定对象和SyncFactory 没有提及供应商,一个SyncFactoryException被抛出。
  • 如果指定了一个SyncProvider对象,并且SyncFactory包含对提供程序的引用,则提供请求的提供程序。
  • 如果没有指定SyncProvider对象,则提供参考实现提供者RIOptimisticProvider

这些政策在SyncFactory课程中有更详细的探讨

3.0 SyncProvider Implementer's Guide

3.1要求

柔顺SyncProvider实现,它是完全可插入到SyncFactory 必须扩展和实施中的所有抽象方法SyncProvider类。 此外,实现必须确定SyncProvider类定义中定义的等级,锁定和可更新视图功能。 必须支持一个或多个SyncProvider描述条件。 预计供应商实施将提供一系列的等级,锁定和可更新视图功能。

另外SyncProvider命名约定必须遵循SyncProvider类的描述。

3.2年级

JSR 114定义了一组等级来描述同步的质量,一个SyncProvider对象可以提供一个断开连接的对象RowSet 这些等级从最低服务质量列为最高。

  • GRADE_NONE - 不提供与始发数据源的同步。 返回此等级的SyncProvider实现将简单地尝试将在RowSet对象中更改的任何数据写入底层数据源,覆盖任何内容。 没有尝试将原始值与当前值进行比较,以查看是否存在冲突。 RIXMLProvider是用这个档次实现的。
  • GRADE_CHECK_MODIFIED_AT_COMMIT - 低级别的乐观同步。 返回此等级的SyncProvider实现将检查在最后一次同步和正在进行的当前同步之间发生变化的行中的冲突。 已修改的始发数据源中的任何更改都不会反映在断开连接的RowSet对象中。 如果没有冲突, RowSet对象中的更改将写入数据源。 如果有冲突,则不会改变。 RIOptimisticProvider实现使用这个等级。
  • GRADE_CHECK_ALL_AT_COMMIT - 高度的乐观同步。 返回此等级的SyncProvider实现将检查所有行,包括已断开连接的RowSet对象中未更改的行。 这样,当同步完成成功时,底层数据源中对行的任何更改将反映在断开连接的RowSet对象中。
  • GRADE_LOCK_WHEN_MODIFIED - 悲观的同步档次。 返回此等级的SyncProvider实现将锁定与RowSet对象中正在更改的行对应的始发数据源中的行,以减少其他进程修改数据源中相同数据的可能性。
  • GRADE_LOCK_WHEN_LOADED - 较高的悲观同步等级。 返回此等级的SyncProvider实现将锁定用于填充RowSet对象的原始查询影响的整个视图和/或表。

3.3锁

JSR 114定义了一组常量,它们指定是否将任何锁放置在RowSet对象的底层数据源上,如果是,则放置锁。 这些锁将保留在数据源上,而RowSet对象与数据源断开连接。

这些常数应该被认为是等级常数的补充。 大多数成绩设置的默认设置要求当RowSet对象与其数据源断开连接时,不会保留数据源锁。 GRADE_LOCK_WHEN_MODIFIEDGRADE_LOCK_WHEN_LOADED等级允许断开连接的RowSet对象对锁定程度进行细粒度控制。

  • DATASOURCE_NO_LOCK - 始发数据源上没有锁。 这是所有SyncProvider实现的默认锁定设置,除非由RowSet对象另有指示。
  • DATASOURCE_ROW_LOCK - 锁被放置在用于填充RowSet对象的原始SQL查询所触摸的行上。
  • DATASOURCE_TABLE_LOCK - 被用于填充RowSet对象的查询所触及的所有表上都放置一个锁。
  • DATASOURCE_DB_LOCKRowSet对象使用的整个数据源上放置一个锁。

3.4可更新视图

可以使用来自SQL VIEW数据填充RowSet对象。 以下常量指示SyncProvider对象是否可以更新派生VIEW的表或表中的数据。

  • UPDATABLE_VIEW_SYNC表示一个SyncProvider实现支持同步到VIEW用于填充RowSet对象的SQL VIEW的表或表。
  • NONUPDATABLE_VIEW_SYNC表示一个SyncProvider实现支持同步从该SQL表或表VIEW用于填充RowSet对象导出。

3.5使用SyncProvider分级和锁定

在下面的示例中,参考CachedRowSetImpl实现通过调用setSyncProvider方法重新配置其当前的SyncProvider对象。

  CachedRowSetImpl crs = new CachedRowSetImpl();
    crs.setSyncProvider("com.foo.bar.HASyncProvider"); 
应用程序可以检索由断开连接的SyncProvider对象当前正在使用的RowSet对象。 它还可以检索提供者实现的同步级别和当前使用的锁定程度。 此外,应用程序具有设置要使用的锁定程度的灵活性,这可以增加成功同步的可能性。 这些操作显示在以下代码片段中。
  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(); 

4.0 Resolving Synchronization Conflicts

接口SyncResolver提供了一种应用程序手动决定冲突发生时该做什么的一种方式。 CachedRowSet方法acceptChanges完成并检测到一个或多个冲突时,它将抛出一个SyncProviderException对象。 应用程序可以捕获异常,并通过调用方法SyncProviderException.getSyncResolver()检索SyncResolver对象。

一个SyncResolver对象,它是一种特殊类型的CachedRowSet对象或JdbcRowSet对象,已实现了SyncResolver接口,逐行检查冲突。 它是复制RowSet对象被同步,除了它只包含来自数据源的数据导致冲突。 所有其他列值都设置为null 要从一个冲突值导航到另一个冲突值,一个SyncResolver对象提供了方法nextConflictpreviousConflict

SyncResolver接口还提供了以下方法:

  • 了解冲突是否涉及更新,删除或插入
  • 获取导致冲突的数据源中的值
  • 如果需要更改,请设置应该在数据源中的值,如果需要更改,则设置应该在RowSet对象中的值

当调用CachedRowSet方法acceptChanges ,它委托给RowSet对象的SyncProvider对象。 如何实现SyncProvider对象提供的作者如何确定检查冲突的级别(等级)。 完成所有检查冲突并完成一个或多个冲突后,方法acceptChanges将抛出一个SyncProviderException对象。 应用程序可以捕获异常并使用它来获取一个SyncResolver对象。

然后,应用程序可以使用SyncResolver方法获取有关每个冲突的信息,并决定要执行的操作。 如果应用程序逻辑或用户决定RowSet对象中的值应该是持久的,应用程序或用户可以使用它来覆盖数据源值。

SyncResolver界面的评论有更多的细节。

5.0 Related Specifications

6.0 Related Documentation