Module java.sql.rowset

Interface SyncResolver

所有超接口:
AutoCloseable, ResultSet, RowSet, Wrapper

public interface SyncResolver extends RowSet
定义了一个框架,允许应用程序使用手动决策树来决定在同步冲突发生时应该执行什么操作。虽然应用程序不一定要手动解决同步冲突,但该框架提供了在冲突发生时委托给应用程序的方式。

请注意,冲突是指RowSet对象的某一行的原始值与数据源中的值不匹配的情况,这表明自上次同步以来数据源行已被修改。还请注意,RowSet对象的原始值是指在上次同步之前它所具有的值,并不一定是其初始值。

描述SyncResolver对象

SyncResolver对象是一个专门实现了SyncResolver接口的RowSet对象。它可以作为连接的RowSet对象(实现了JdbcRowSet接口)或连接的RowSet对象(实现了CachedRowSet接口或其子接口之一)运行。有关子接口的信息,请参阅javax.sql.rowset包描述。 SyncResolver的参考实现实现了CachedRowSet接口,但其他实现可以选择实现JdbcRowSet接口以满足特定需求。

当应用程序尝试将RowSet对象与数据源同步(通过调用CachedRowSet方法acceptChanges),并且发现一个或多个冲突时,一个rowset的SyncProvider对象会创建一个SyncResolver实例。这个新的SyncResolver对象与尝试同步的RowSet对象具有相同数量的行和列。 SyncResolver对象包含导致冲突的数据源值,对于所有其他值则为null。此外,它还包含有关每个冲突的信息。

获取和使用SyncResolver对象

当方法acceptChanges遇到冲突时,SyncProvider对象会创建一个SyncProviderException对象,并将其设置为新的SyncResolver对象。方法acceptChanges将抛出此异常,应用程序可以捕获并使用它来检索其中包含的SyncResolver对象。以下代码片段使用SyncProviderException方法getSyncResolver来获取SyncResolver对象resolver
 
      catch (SyncProviderException spe) {
         SyncResolver resolver = spe.getSyncResolver();
     ...
     }

 }
 

有了resolver,应用程序可以使用它来获取有关冲突的信息。例如,SyncResolver对象(如resolver)会跟踪每个存在冲突的行的冲突。它还会对受到rowset命令影响的表或表放置锁定,以防止在解决当前冲突时发生更多冲突。

可以从SyncResolver对象中获取以下类型的信息:

冲突发生时正在尝试的操作

SyncProvider接口定义了四个描述可能发生的状态的常量。三个常量描述了当发现冲突时RowSet对象尝试执行的操作类型(更新、删除或插入),第四个指示没有冲突。当SyncResolver对象调用方法getStatus时,这些常量是可能的返回值。
     int operation = resolver.getStatus(); 
 

导致冲突的数据源中的值

RowSet对象已更改并尝试写入数据源的值在自上次同步以来也已在数据源中更改时,就会出现冲突。应用程序可以调用SyncResolver方法getConflictValue来检索导致冲突的数据源中的值,因为SyncResolver对象中的值是来自数据源的冲突值。
     java.lang.Object conflictValue = resolver.getConflictValue(2);
 
请注意,resolver中的列可以通过列号指定,就像在上述代码行中所做的那样,也可以通过列名指定。

通过从方法getStatusgetConflictValue中检索的信息,应用程序可以确定应该将哪个值持久化到数据源。然后,应用程序调用SyncResolver方法setResolvedValue,该方法设置要在RowSet对象和数据源中持久化的值。

     resolver.setResolvedValue("DEPT", 8390426);
 
在上述代码行中,列名指定了要使用给定值设置的RowSet对象中的列。也可以使用列号来指定列。

应用程序在解决当前冲突行的所有冲突后调用方法setResolvedValue,并为SyncResolver对象中的每个冲突行重复此过程。

由于SyncResolver对象是一个RowSet对象,应用程序可以使用所有RowSet方法来移动光标以导航SyncResolver对象。例如,应用程序可以使用RowSet方法next来移动到每一行,然后调用SyncResolver方法getStatus来查看该行是否包含冲突。在具有一个或多个冲突的行中,应用程序可以通过列来迭代以查找任何非空值,这些值将是数据源中存在冲突的值。

为了更容易地导航SyncResolver对象,特别是当存在大量没有冲突的行时,SyncResolver接口定义了方法nextConflictpreviousConflict,它们仅移动到至少包含一个冲突值的行。然后,应用程序可以调用SyncResolver方法getConflictValue,并提供列号,以获取冲突值本身。下一节的代码片段给出了一个示例。

代码示例

以下代码片段演示了一个断开连接的RowSet对象crs如何尝试将自身与底层数据源同步,然后解决冲突。在try块中,crs调用方法acceptChanges,并传递Connection对象con。如果没有冲突,则 中的更改将简单地写入数据源。但是,如果存在冲突,方法 acceptChanges会抛出一个 SyncProviderException对象,然后 catch块生效。在这个示例中,展示了 SyncResolver对象的一种用法, SyncResolver方法 nextConflict在一个 while循环中使用。当 nextConflict返回 false时,循环将结束,这将在 SyncResolver对象 resolver中没有更多冲突行时发生。在这个特定的代码片段中, resolver查找具有更新冲突的行(具有状态 SyncResolver.UPDATE_ROW_CONFLICT的行),并且仅对因为 crs尝试更新而发生冲突的行执行此代码片段的其余部分。

resolver的光标移动到具有更新冲突的下一个冲突行后,方法getRow指示当前行的编号,CachedRowSet对象crs的光标移动到crs中的可比较行。通过在resolvercrs中的该行的列上进行迭代,可以检索并比较冲突值,以决定应该持久化哪个值。在这个代码片段中,crs中的值被设置为解决值,这意味着它将用于覆盖数据源中的冲突值。

 
     try {

         crs.acceptChanges(con);

     } catch (SyncProviderException spe) {

         SyncResolver resolver = spe.getSyncResolver();

         Object crsValue;  // RowSet对象中的值
         Object resolverValue:  // SyncResolver对象中的值
         Object resolvedValue:  // 要持久化的值

         while(resolver.nextConflict())  {
             if(resolver.getStatus() == SyncResolver.UPDATE_ROW_CONFLICT)  {
                 int row = resolver.getRow();
                 crs.absolute(row);

                 int colCount = crs.getMetaData().getColumnCount();
                 for(int j = 1; j <= colCount; j++) {
                     if (resolver.getConflictValue(j) != null)  {
                         crsValue = crs.getObject(j);
                         resolverValue = resolver.getConflictValue(j);
                         . . .
                         // 比较crsValue和resolverValue以确定
                         // 哪个应该是解决值(要持久化的值)
                         resolvedValue = crsValue;

                         resolver.setResolvedValue(j, resolvedValue);
                      }
                  }
              }
          }
      }
 
自JDK版本:
1.5
  • Field Details

    • UPDATE_ROW_CONFLICT

      static final int UPDATE_ROW_CONFLICT
      指示在RowSet对象尝试更新数据源中的行时发生冲突。数据源行中要更新的值与该行的原始值不同,这意味着自上次同步以来,数据源中的行已被更新或删除。
      参见:
    • DELETE_ROW_CONFLICT

      static final int DELETE_ROW_CONFLICT
      指示在RowSet对象尝试从数据源中删除行时发生冲突。要更新的数据源行中的值与该行的原始值不同,这意味着自上次同步以来,数据源中的行已被更新或删除。
      参见:
    • INSERT_ROW_CONFLICT

      static final int INSERT_ROW_CONFLICT
      指示在RowSet对象尝试将行插入数据源时发生冲突。这意味着自上次同步以来,已将具有与要插入的行相同主键的行插入到数据源中。
      参见:
    • NO_ROW_CONFLICT

      static final int NO_ROW_CONFLICT
      指示在RowSet对象尝试更新、删除或插入数据源中的行时未发生冲突。 SyncResolver中的值仅包含null值,表示在此行的冲突解决中没有相关信息。
      参见:
  • Method Details

    • getStatus

      int getStatus()
      检索此SyncResolver当前行的冲突状态,该状态指示RowSet对象在冲突发生时尝试的操作。
      返回:
      以下常量之一:SyncResolver.UPDATE_ROW_CONFLICTSyncResolver.DELETE_ROW_CONFLICTSyncResolver.INSERT_ROW_CONFLICTSyncResolver.NO_ROW_CONFLICT
    • getConflictValue

      Object getConflictValue(int index) throws SQLException
      检索当前行中指定列的值,该行位于此SyncResolver对象中,该值是导致冲突的数据源中的值。
      参数:
      index - 一个int,指定要检索导致冲突的值的SyncResolver对象中的行中的列
      返回:
      SyncResolver对象当前行中指定列的值
      抛出:
      SQLException - 如果发生数据库访问错误
    • getConflictValue

      Object getConflictValue(String columnName) throws SQLException
      检索当前行中指定列的值,该行位于此SyncResolver对象中,该值是导致冲突的数据源中的值。
      参数:
      columnName - 一个String对象,指定要检索导致冲突的值的SyncResolver对象中的行中的列
      返回:
      SyncResolver对象当前行中指定列的值
      抛出:
      SQLException - 如果发生数据库访问错误
    • setResolvedValue

      void setResolvedValue(int index, Object obj) throws SQLException
      obj设置为正在同步的RowSet对象当前行中列index的值。 obj在内部设置为数据源中的值。
      参数:
      index - 一个int,表示要将值设置为要持久化的列的编号
      obj - 一个Object,是要在RowSet对象中设置并在数据源中持久化的值
      抛出:
      SQLException - 如果发生数据库访问错误
    • setResolvedValue

      void setResolvedValue(String columnName, Object obj) throws SQLException
      obj设置为正在同步的RowSet对象当前行中列columnName的值。 obj在内部设置为数据源中的值。
      参数:
      columnName - 一个String对象,表示要将值设置为要持久化的列的名称
      obj - 一个Object,是要在RowSet对象中设置并在数据源中持久化的值
      抛出:
      SQLException - 如果发生数据库访问错误
    • nextConflict

      boolean nextConflict() throws SQLException
      将光标从当前位置向下移动到下一行,该行包含冲突值。 SyncResolver对象的光标最初位于第一个冲突行之前;第一次调用方法nextConflict将第一个冲突行设置为当前行;第二次调用将第二个冲突行设置为当前行,依此类推。

      调用方法nextConflict将隐式关闭输入流(如果已打开),并将清除SyncResolver对象的警告链。

      返回:
      如果新的当前行有效,则为true;如果没有更多行,则为false
      抛出:
      SQLException - 如果发生数据库访问错误或结果集类型为TYPE_FORWARD_ONLY
    • previousConflict

      boolean previousConflict() throws SQLException
      将光标从当前位置向上移动到此SyncResolver对象中的上一冲突行。

      调用方法previousConflict将隐式关闭输入流(如果已打开),并将清除SyncResolver对象的警告链。

      返回:
      如果光标位于有效行上,则为true;如果光标位于结果集之外,则为false
      抛出:
      SQLException - 如果发生数据库访问错误或结果集类型为TYPE_FORWARD_ONLY