模块  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对象,该对象具有将数据读入其中以及将已在其中修改的数据写回底层数据源的机制。 CachedRowSet方法executepopulate时,读取 RowSetReaderXMLReader对象将数据读入RowSet对象。 作家RowSetWriterXMLWriter当对象,写入变回底层数据源CachedRowSet方法acceptChanges被调用。

RowSet对象中的更改写入其数据源的过程称为同步 所述SyncProvider实现,一个RowSet对象是使用判定同步的水平RowSet对象的作者使用。 各种级别的同步称为等级

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

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

最低级别的同步只是将对RowSet对象所做的任何更改写入其基础数据源。 作者没有做任何事情来检查冲突。 如果存在冲突并且数据源值被覆盖,则其他方对数据源所做的更改将丢失。

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

对于下一级别,编写器检查是否存在任何冲突,如果存在冲突,则不会向数据源写入任何内容。 此并发级别的问题是,如果另一方修改了数据源中的相应数据,因为RowSet对象获取了其数据,则对RowSet对象所做的更改将丢失。 RIOptimisticProvider实现使用此级别的同步。

在更高级别的同步(称为悲观并发)时,编写器通过设置锁来采取措施来避免冲突。 设置锁定可以从设置单个行上的锁定到设置表格锁定或整个数据源。 因此,同步级别是用户同时访问数据源的能力与写入器保持RowSet对象中的数据及其数据源同步的能力之间的权衡。

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

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

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

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

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

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

2.0 Service Provider Interface Architecture

2.1概述

服务提供程序接口提供了一种可插入的机制,通过该机制可以注册SyncProvider实现,然后在需要时生成。 SyncFactory使用的惰性引用机制通过在断开的RowSet对象需要之前不创建实例SyncFactory限制不必要的资源消耗。 SyncFactory类还提供了一个标准API,用于配置特定SyncProvider实现可能提供的日志记录选项和流。

2.2注册SyncFactory

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

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

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

2.3 SyncFactory提供程序实例生成策略

如果提供程序已正确注册, 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对象中。 如果没有冲突, RowSetRowSet对象中的更改写入数据源。 如果存在冲突,则不会写入任何更改。 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_LOCK锁定放置在RowSet对象使用的整个数据源上。

3.4可更新视图

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

  • UPDATABLE_VIEW_SYNC指示SyncProvider实现支持与用于填充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对象或实现了SyncResolver接口的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