Java 6 RowSet 使用完全剖析(3)

来源:互联网 发布:淘宝网logo矢量图 编辑:程序博客网 时间:2024/06/06 19:14

Java 6 RowSet 使用完全剖析(3)

关键字: rowset

清单 24. 清单 23 中的代码执行结果

1 Tom Tom is VIP. 2 Jim null

下面一节里我们将会看到 JdbcRowSet 如何作为一个 RowSet 和其他的 RowSet 一起使用。

使用 JoinRowSet

 

支持的联合方式

JoinRowSet 接口中对五种不同的联合方式都定义了对应的常数和判断该实现是否支持的方法,如下表所示。

表 5. 五种联合方式

联合方式 对应的常数 判断是否支持的方法(返回布尔值)
内连接(INNER JOIN) JoinRowSet.INNER_JOIN supportsInnerJoin()
左外连接(LEFT OUTER JOIN)  JoinRowSet.LEFT_OUTER_JOIN supportsLeftOuterJoin()
右外连接(RIGHT OUTER JOIN)  JoinRowSet.RIGHT_OUTER_JOIN supportsRightOuterJoin() 
全外连接(FULL OUTER JOIN) JoinRowSet.FULL_JOIN supportsFullJoin()
交叉连接(CROSS JOIN)  JoinRowSet.CROSS_JOIN supportsCrossJoin()


同时还有两个方法,getJoinType() 返回当前的联合方式,setJoinType(int) 设置联合方式。值得注意的是,Java 5 和 Java 6 中都支持内连接 (INNER JOIN) 这一种联合方式。在 setJoinType 方法中传入除 Inner_Join 以外的任何一种联合方式都会抛出 UnsupportedOperationException 的异常。

另外一点需要注意的,虽然默认的联合方式就是内连接,但是在没有显示的调用 setJoinType() 之前调用 getJoinType() 会抛出 ArrayIndexOutOfBoundsException 的异常。 所以一般来讲,我们可以不需要调用这几个方法而直接认为 JoinRowSet 默认并且只允许的联合方式就是内连接(INNER JOIN)。

 

如何联合各种 RowSet

联合多个 RowSet 的方法其实就是往一个 JoinRowSet 里调用 add 方法添加其他 RowSet(这个 RowSet 可以是上面提到的五种 RowSet 中的任意一种,包括离线操作的 JdbcRowSet 和 JoinRowSet 本身)的过程。添加一个 RowSet 的同时也必须制定联合时匹配的列。JoinRowSet 接口中提供了以下几个 add 方法:

addRowSet(Joinable rowset)
addRowSet(RowSet[] rowset, int[] columnIdx)
addRowSet(RowSet[] rowset, String[] columnName)
addRowSet(RowSet rowset, int columnIdx)
addRowSet(RowSet rowset, String columnName)
下面是一个联合一个 JdbcRowSet 和一个 CachedRowSet 的简单例子。


清单 25. 使用 JoinRowSet

// 构造一个CachedRowSet并且填充CUSTOMERS表中的数据。

Java代码 复制代码
  1. CachedRowSet cachedRS = new CachedRowSetImpl();    
  2. cachedRS.setUrl(DBCreator.DERBY_URL);    
  3. cachedRS.setCommand(DBCreator.SQL_SELECT_CUSTOMERS);    
  4. cachedRS.execute(); // 构造一个JdbcRowSet并且填充ORDERS表中的数据。    
  5. JdbcRowSet jdbcRS = new JdbcRowSetImpl();    
  6. jdbcRS.setUrl(DBCreator.DERBY_URL);    
  7. jdbcRS.setCommand(DBCreator.SQL_SELECT_ORDERS); jdbcRS.execute(); // 把cachedRS添加进新构造的JoinRowSet中。 JoinRowSet joinRS = new JoinRowSetImpl();    
  8. joinRS.addRowSet(cachedRS, "ID"); //$NON-NLS-1$    
  9. // 下面这条被注释的语句会抛出ClassCastExcepion。 // joinRS.addRowSet(jdbcRS, "ID"); // 把jdbcRS添加进这个JoinRowSet中。    
  10. jdbcRS.setMatchColumn("ID"); //$NON-NLS-1$    
  11. joinRS.addRowSet(jdbcRS); // 观察结果    
  12. printRowSet(joinRS);   

 

清单 26. 清单 25 中的代码执行结果

 

The data in CachedRowSet: 2 Jim null 1 Compute 1 Tom Tom is VIP. 1 Book 

 

虽然 JoinRowSet 提供了五个不同的 addRowSet 方法,但是对于某些 RowSet,并不是每个方法都能用的。比如当上面添加一个 JdbcRowSet 的时候,你只能调用 addRowSet(Joinable) 这个方法(JdbcRowSet 实现了 Joinable 接口),并且在调用这个方法之前一定要先设置配对的列名或者以 1 为基数的配对列的位置,如下所示。

 

清单 27. 添加 JdbcRowSet

Java代码 复制代码
  1. // 正确的添加一个JdbcRowSet的方法。    
  2. jdbcRS.setMatchColumn("ID");    
  3. joinRS.addRowSet(jdbcRS);   

  

输出结果表明此时 JoinRowSet 中的数据正是两个 RowSet 中的数据的内联结果。加进去的两个 RowSet 中的”ID”这一列,在 JoinRowSet 中合并成了一列。如果我们查看最后 JoinRowSet 的列名,会发现这一列的列名变成了”MergedCol”, 其它列名不变。这个时候的 JoinRowSet 可以继续添加其他的 RowSet,联合会在 MergedCol 这一列上进行。

 

清单 28. 查看 JoinRowSet 中列名

Java代码 复制代码
  1. for (int i = 1; i <= joinRS.getMetaData().getColumnCount(); i++)    
  2. {    
  3.      System.out.println(joinRS.getMetaData().getColumnName(i));    
  4. }    

 

 

清单29. 清单 28 中的代码执行结果

MergedCol NAME REMARK USER_ID PRODUCT 

 

JoinRowSet 作为 CachedRowSet 的使用

从前面的继承结构图可以看到,JoinRowSet 继续于 CachedRowSet。因此从理论上来看,JoinRowSet 也可以作为 CachedRowSet 来使用。

 

但是其实 JoinRowSet 很多方法并不是简单的直接继承 CachedRowSet 中的方法,而是重写(Override)了这些方法。最典型的两个方法是 execute 和 populate。 前面已经提到过,这是两种填充一个 CachedRowSet 的方法。但是对于 JoinRowSet,这两个方法却不起作用,不应该被使用。

另外一个比较特殊的方法是 acceptChanges。当 JoinRowSet 中包含一个 CachedRowSet 的时候,这个方法可以使用,并且效果就相当于在里面的这个 CachedRowSet 里面调用。但是当 JoinRowSet 包含两个或多个 RowSet 的时候,这个方法就不起作用了。这就类似于数据库多表联结后形成的视图(View),一般是不能够进行更新操作的。

应注意的问题

虽然 JoinRowSet 提供了五个不同的 addRowSet 方法,但是并不是对于每个 RowSet 这五个方法都是可行的。这点前面已经提到过。
程序不能依赖 JoinRowSet 中的数据的顺序。JoinRowSet 接口中并没有能够控制连接结果排序的方法。它只能保证最后连接结果的正确性,但不能保证顺序。
当把一个 RowSet 加入到 JoinRowSet 中,这个作为 addRowSet 方法的参数的 RowSet 的指针位置可能发生变化。另外当这个 RowSet 是 JdbcRowSet 的时候,在通过 addRowSet 方法加入之前,如果该 JdbcRowSet 的指针位置发生变化的时候,也会影响联合的结果。请看下面这个例子(假设我们已经像前面一样构造好了一个 CachedRowSet 和一个 JdbcRowSet):

 

清单 30

Java代码 复制代码
  1. // 添加cachedRS. JoinRowSet joinRS = new JoinRowSetImpl();    
  2. joinRS.addRowSet(cachedRS, "ID");     
  3. // 在添加jdbcRS之前,改变指针的位置。    
  4. jdbcRS.next();    
  5. jdbcRS.setMatchColumn("ID");    
  6. joinRS.addRowSet(jdbcRS);    
  7. // 观察结果 printRowSet(joinRS);    

 


清单 31. 清单 30 中的代码执行结果

The data in CachedRowSet: 2 Jim null 1 Compute 

由于 jdbcRS 在加入之前,指针位置发生了变化,导致联结后的结果不一样了。实际上,由于 jdbcRS 是保持数据库连接的,所以一般只能够进行查看下一条数据的操作,而不能查看已经前面的数据,所以当把一个 JdbcRowSet 加入到 JoinRowSet 中时,我们只相当于对这个 JdbcRowSet 从当前位置开始的数据进行了联结操作,而忽略了处于当前指针位置前面的数据。

那么,对于 CachedRowSet,情况又是怎么样呢?

 

清单 32

Java代码 复制代码
  1. // 添加jdbcRS. JoinRowSet joinRS = new JoinRowSetImpl();    
  2.   
  3. jdbcRS.setMatchColumn("ID"); //$NON-NLS-1$    
  4.   
  5. joinRS.addRowSet(jdbcRS); // 在添加cachedRS之前,改变指针的位置。    
  6.   
  7. cachedRS.last();    
  8.   
  9. joinRS.addRowSet(cachedRS, "ID"); //$NON-NLS-1$ // 结果. 此时JoinRowSet中的数据。    
  10.   
  11. printRowSet(joinRS);    

 


清单 33. 清单 32 中的代码执行结果

The data in CachedRowSet: 2 1 Compute Jim null 1 1 Book Tom Tom is VIP. 

由此可见,即使 cachedRS 在加入之前,指针位置发生了变化,也不会影响联结的结果。这是因为 CachedRowSet 是离线的,可以前后滚动查看数据。

结束语

本文介绍了 javax.sql.rowset 包下五个 RowSet 接口的使用,并重点说明了在使用中可能出现的问题。合理利用 RowSet 提供的离线式数据处理功能可以达到事半功倍的效果。

 

描述 名字 大小 下载方法
本文用到的 Java 示例代码 RowSetDemo.zip 21 KB HTTP