Package javax.sql.rowset.spi
RowSet
对象能够使用一个实现,供应商必须将其注册到SyncFactory
单例中。(请参阅SyncProvider
的类注释,了解注册过程和要使用的命名约定的详细说明。)
目录
1.0 包规范
以下类和接口组成了javax.sql.rowset.spi
包:
SyncFactory
SyncProvider
SyncFactoryException
SyncProviderException
SyncResolver
XmlReader
XmlWriter
TransactionalWriter
javax.sql
包中,也是SPI的一部分:
RowSetReader
RowSetWriter
SyncProvider
实现为一个断开连接的RowSet
对象提供了读取数据和将已修改数据写回底层数据源的机制。一个读取器,即RowSetReader
或XMLReader
对象,在调用CachedRowSet
方法execute
或populate
时将数据读入RowSet
对象。一个写入器,即RowSetWriter
或XMLWriter
对象,在调用CachedRowSet
方法acceptChanges
时将更改写回底层数据源。
将RowSet
对象中的更改写入其数据源的过程称为同步。RowSet
对象的写入器使用的同步级别由RowSet
对象的写入器决定。各种同步级别被称为等级。
较低级别的同步被称为乐观并发级别,因为它们乐观地假设不会发生冲突或很少发生冲突。当在RowSet
对象中修改的相同数据也在数据源中被修改时,就会存在冲突。使用乐观并发模型意味着如果存在冲突,则对数据源或RowSet
对象的修改将会丢失。
较高级别的同步被称为悲观,因为它们假设其他人将访问数据源并进行修改。这些级别设置不同级别的锁,以增加冲突不发生的机会。
最低级别的同步仅是将RowSet
对象中所做的任何更改写入其底层数据源。写入器不会检查冲突。如果存在冲突并且数据源值被覆盖,则其他方对数据源所做的更改将丢失。
RIXMLProvider
实现使用最低级别的同步,只是将RowSet
的更改写入数据源。
在更高级别的同步中,称为悲观并发,写入器会采取措施避免冲突,通过设置锁。设置锁可以从在单个行上设置锁到在表或整个数据源上设置锁。因此,同步级别是用户同时访问数据源的能力和写入器保持RowSet
对象及其数据源同步的能力之间的权衡。
所有断开连接的RowSet
对象(CachedRowSet
、FilteredRowSet
、JoinRowSet
和WebRowSet
对象)都必须从SyncFactory
机制中获取它们的SyncProvider
对象。
参考实现(RI)提供了两个同步提供程序。
RIOptimisticProvider
当未指定提供程序实现时,SyncFactory
实例将为断开连接的RowSet
对象提供默认提供程序。
这个同步提供程序使用乐观并发模型,假设在数据库中访问相同数据的用户之间很少发生冲突。它避免使用锁;相反,它在尝试同步RowSet
对象和数据源之前检查是否存在冲突。如果存在冲突,它不执行任何操作,这意味着RowSet
对象的更改不会持久保存到数据源。RIXMLProvider
一个同步提供程序,可与WebRowSet
对象一起使用,这是一个可以以XML格式编写或从XML格式读取的行集。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
对象提供同步机制的选择。
2.0 服务提供程序接口架构
2.1 概述服务提供程序接口提供了一种可插拔机制,通过该机制,可以注册SyncProvider
实现,并在需要时生成。SyncFactory
采用的延迟引用机制通过仅在断开连接的RowSet
对象需要时才创建实例,从而限制了不必要的资源消耗。SyncFactory
类还提供了一个标准API,用于配置可能由特定SyncProvider
实现提供的日志选项和流。
2.2 注册到SyncFactory
第三方SyncProvider
实现必须在SyncFactory
中注册,以便断开连接的RowSet
对象获取它,并因此使用其javax.sql.RowSetReader
和javax.sql.RowSetWriter
实现。所有SyncProvider
实现都可以使用以下注册机制:
- 系统属性 - 在命令行设置的属性。这些属性在运行时设置,并且每次调用Java应用程序时都适用于整个系统。有关更多相关信息,请参见"相关文档"部分。
- 属性文件 - 在标准属性文件中指定的属性。这可以使用系统属性指定,也可以通过修改位于平台运行时位置的标准属性文件来指定。该技术的参考实现包括一个标准属性文件,可以编辑以添加其他
SyncProvider
对象。 - JNDI上下文 - 可以在JNDI上下文中注册可用的提供程序。
SyncFactory
将尝试加载绑定到上下文并将其注册到工厂的SyncProvider
对象。必须将此上下文提供给SyncFactory
,以使机制正常运行。
有关如何指定系统属性或属性文件中的属性以及如何配置JNDI上下文的详细信息,请参阅SyncFactory
类描述。
2.3 SyncFactory提供程序实例生成策略
如果已正确注册提供程序,则SyncFactory
将生成请求的SyncProvider
对象。当实例化断开连接的RowSet
对象时指定了特定的SyncProvider
实现,或者在运行时使用替代的SyncProvider
对象重新配置时,将遵守以下策略:
- 如果指定了
SyncProvider
对象,但SyncFactory
不包含对该提供程序的引用,则会抛出一个SyncFactoryException
。 - 如果指定了
SyncProvider
对象,并且SyncFactory
包含对该提供程序的引用,则提供请求的提供程序。 - 如果未指定
SyncProvider
对象,则提供参考实现提供程序RIOptimisticProvider
。
这些策略在 SyncFactory
类中有更详细的探讨。
3.0 SyncProvider实现者指南
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_MODIFIED
和GRADE_LOCK_WHEN_LOADED
允许断开连接的RowSet
对象对锁定程度进行精细控制。
- DATASOURCE_NO_LOCK - 在原始数据源上不保留任何锁。这是所有
SyncProvider
实现的默认锁设置,除非RowSet
对象另有指示。 - DATASOURCE_ROW_LOCK - 在由用于填充
RowSet
对象的原始SQL查询触及的行上放置锁。 - DATASOURCE_TABLE_LOCK - 在由用于填充
RowSet
对象的查询触及的所有表上放置锁。 - DATASOURCE_DB_LOCK - 在由
RowSet
对象使用的整个数据源上放置锁。
3.4 可更新视图
RowSet
对象可以使用来自SQL VIEW
的数据填充。以下常量指示SyncProvider
对象是否可以更新从中派生VIEW
的表或表中的数据。
- UPDATABLE_VIEW_SYNC - 表示
SyncProvider
实现支持将数据同步到用于填充RowSet
对象的SQLVIEW
所派生的表或表。 - NONUPDATABLE_VIEW_SYNC - 表示
SyncProvider
实现不支持将数据同步到用于填充RowSet
对象的SQLVIEW
所派生的表或表。
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 //一种乐观同步的高等级 break; case: SyncProvider.GRADE_CHECK_MODIFIED_AT_COMMIT //一种乐观同步的低等级 break; case: SyncProvider.GRADE_LOCK_WHEN_LOADED // 一种悲观同步等级 break; case: SyncProvider.GRADE_LOCK_WHEN_MODIFIED // 一种悲观同步等级 break; case: SyncProvider.GRADE_NONE // 不提供与原始数据源的同步 break; } switch (sync.getDataSourceLock() { case: SyncProvider.DATASOURCE_DB_LOCK // 在还可以使用RowSet
对象使用的整个数据源上放置锁 break; case: SyncProvider.DATASOURCE_NO_LOCK // 在原始数据源上不保留任何锁 break; case: SyncProvider.DATASOURCE_ROW_LOCK // 在由用于填充RowSet
对象的原始SQL语句触及的行上放置锁 break; case: DATASOURCE_TABLE_LOCK // 在由用于填充RowSet
对象的原始SQL语句触及的所有表上放置锁 break;
SyncFactory
类中的静态实用方法确定当前已注册到SyncFactory
的SyncProvider
实现列表。
Enumeration e = SyncFactory.getRegisteredProviders();
4.0 解决同步冲突
接口SyncResolver
提供了一种应用程序在发生冲突时手动决定如何处理的方法。当CachedRowSet
方法acceptChanges
完成并检测到一个或多个冲突时,它会抛出一个SyncProviderException
对象。应用程序可以捕获异常,并通过调用方法SyncProviderException.getSyncResolver()
来检索一个SyncResolver
对象。
SyncResolver
对象是一种特殊类型的CachedRowSet
对象或实现了SyncResolver
接口的JdbcRowSet
对象,逐行检查冲突。它是正在同步的RowSet
对象的副本,但它只包含来自导致冲突的数据源的数据。所有其他列值设置为null
。要从一个冲突值导航到另一个冲突值,SyncResolver
对象提供了nextConflict
和previousConflict
方法。
SyncResolver
接口还提供以下方法:
- 查找冲突是否涉及更新、删除或插入
- 获取导致冲突的数据源中的值
- 设置应该在数据源中的值(如果需要更改)或设置应该在
RowSet
对象中的值(如果需要更改)
当调用CachedRowSet
方法acceptChanges
时,它会委托给RowSet
对象的SyncProvider
对象。由该SyncProvider
对象提供的写入器的实现方式决定将进行何种级别(等级)的冲突检查。在完成所有冲突检查并发现一个或多个冲突后,方法acceptChanges
会抛出一个SyncProviderException
对象。应用程序可以捕获异常并使用它来获取一个SyncResolver
对象。
然后,应用程序可以使用SyncResolver
方法获取有关每个冲突的信息并决定如何处理。如果应用程序逻辑或用户决定RowSet
对象中的值应该是要持久化的值,则应用程序或用户可以用其覆盖数据源值。
SyncResolver
接口的注释中有更多详细信息。
5.0 相关规范
6.0 相关文档
-
ClassDescription生成供断开的
RowSet
对象使用的SyncProvider
实例的服务提供者接口(SPI)机制。表示SyncFactory
机制出现错误。为断开的RowSet
对象提供读取/写入功能的同步机制。表示SyncProvider
机制出现错误。定义了一个框架,允许应用程序使用手动决策树来决定在同步冲突发生时应该执行什么操作。一种专门的接口,促进了标准SyncProvider
抽象类的扩展,使其具有更精细的事务控制。一种专门的接口,促进了针对XML导向同步提供程序的SyncProvider
抽象类的扩展。一种专门的接口,促进了针对XML导向同步提供程序的SyncProvider
抽象类的扩展。