Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 376|回复: 0

[JDBC学习]分析JDBC ResultSet

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-10-11 04:13:08 | 显示全部楼层 |阅读模式
    JDBC1.0 、JDBC2.0 、JDBC3.0 中分别用以下方法创建Statement 。
    JDBC1.0 : createStatement()
    JDBC2.0 : createStatement(resultSetType, resultSetConcurrency)
    JDBC3.0 : createStatement(resultSetType, resultSetConcurrency, resultSetHoldability)  
         下面依次分析resultSetType 、resultSetConcurrency 、resultSetHoldability 这几个参数的含义。
        一 ResultSetType
              resultSetType 的可选值有: ResultSet.TYPE_FORWARD_ONLY 、ResultSet.TYPE_SCROLL_INSENSITIVE 、ResultSet.TYPE_SCROLL_SENSITIVE 。  
        1 :ResultSet.TYPE_FORWARD_ONLY
        默认的cursor 类型,仅仅支持结果集forward ,不支持backforward ,random ,last ,first 等操作。   
        2 :ResultSet.TYPE_SCROLL_INSENSITIVE
        支持结果集backforward ,random ,last ,first 等操作,对其它session 对数据库中数据做出的更改是不敏感的。  
        实现方法:从数据库取出数据后,会把全部数据缓存到cache 中,对结果集的后续操作,是操作的cache 中的数据,数据库中记录发生变化后,不影响cache 中的数据,所以ResultSet 对结果集中的数据是INSENSITIVE 的。
        3 :ResultSet.TYPE_SCROLL_SENSITIVE
        支持结果集backforward ,random ,last ,first 等操作,对其它session 对数据库中数据做出的更改是敏感的,即其他session 修改了数据库中的数据,会反应到本结果集中。  
        实现方法:从数据库取出数据后,不是把全部数据缓存到cache 中,而是把每条数据的rowid 缓存到cache 中,对结果集后续操作时,是根据rowid 再去数据库中取数据。所以数据库中记录发生变化后,通过ResultSet 取出的记录是最新的,即ResultSet 是SENSITIVE 的。 但insert 和delete 操作不会影响到ResultSet ,因为insert 数据的rowid 不在ResultSet 取出的rowid 中,所以insert 的数据对ResultSet 是不可见的,而delete 数据的rowid 依旧在ResultSet 中,所以ResultSet 仍可以取出被删除的记录( 因为一般数据库的删除是标记删除,不是真正在数据库文件中删除 )。  
        做个试验,验证一下SENSITIVE 特性。数据库为oracle10g ,驱动为ojdbc14.jar 。  
        test 表中数据如下:
         
          
          
           c1
           c2
           c3
          
          
           1c1
           1c2
           1c3
          
          
           2c1
           2c2
           2c3
          
          
           3c1
           3c2
           3c3
          
          
         
        程序如下:
        public static void testResultSetSensitive(Connection conn) throws Exception{
    String sql = "SELECT c1,c2,c3 FROM test";
            try {
            Statement stmt =
           conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
                           
            ResultSet rs = stmt.executeQuery(sql);
                           
            while (rs.next()) {
             System.out.println("[行号:" + rs.getRow() + "]        " + rs.getString(1) + "        " + rs.getString(2)
                    + "        " + rs.getString(3));
              Thread.sleep(20000);
            }
                           
            rs.close();
            stmt.close();
            } catch (SQLException e) {
                    e.printStackTrace();
            } finally {
             try {
                    conn.close();
            } catch (Exception e) {
                    }
            }
    }
            [/code]
        定义ResultSet 为 ResultSet. TYPE_SCROLL_SENSITIVE 类型,首先执行 sql 访问数据库,然后执行 rs.next() 移动游标取数据。在循环里面加上 Thread.sleep (20000) 的目的是为了我们有时间在后台把数据库里的数据改了。比如当在循环里打印出第一行的数据后,我们在后台,把第三行数据的 c3 列改成 ”3uuu” 。如果 ResultSet 真的是敏感的话,那应该取出 ”3uuu” ,而不是原始的“ 3c 3 ”。但最终的结果却是如下:
        [ 行号: 1] 1c1   1c2   1c3
    [ 行号: 2] 2c1   2c2   2c3
    [ 行号: 3] 3c1   3c2   3c3
        数据没变呀,ResultSet 不敏感啊!于是去查阅资料,找了n 久,还是在英文文档上找到了答案。原来是fetchsize 的问题。调用ResultSet 的next 方法取数据时,并不是每调用一次方法就去数据库里查一次,而是有个fetchSize, 一次取fetchSize 条数据。Oracle 默认的fetchsize 等于10 ,所以上面的代码在第一次调用rs.next() 时,就已经把3 条数据都取出来了,所以才会有上面的结果。  
              第二次实验,在ResultSet rs = stmt.executeQuery(sql); 前面加上 stmt.setFetchSize(1); 将fetchSize 设置为1 。然后重新第一次实验的步骤,发现最 终结果为:  
        [ 行号: 1] 1c1   1c2   1c3  
        [ 行号: 2] 2c1   2c2   2c3  
        [ 行号: 3] 3c1   3c2   3uuu  
            原因就是 fetchsize 设置为 1 时,每次 next 取数时都会重新用 rowid 取数据库里取数据,当然取到的是最新的数据了。
              二 ResultSetConcurrency
              ResultSetConcurrency的可选值有2个:
           ResultSet.CONCUR_READ_ONLY 在ResultSet中的数据记录是只读的,不可以修改
           ResultSet.CONCUR_UPDATABLE 在ResultSet中的数据记录可以任意修改,然后更新到数据库,可以插入,删除,修改。
              三 ResultSetHoldability
        ResultSetHoldability 的可选值有2 个 :  
             HOLD_CURSORS_OVER_COMMIT: 在事务commit 或rollback 后,ResultSet 仍然可用。
          CLOSE_CURSORS_AT_COMMIT: 在事务commit 或rollback 后,ResultSet 被关闭。  
             需要注意的地方:  
           1 :Oracle 只支持HOLD_CURSORS_OVER_COMMIT 。  
           2 :当Statement 执行下一个查询,生成第二个ResultSet 时,第一个ResultSet 会被关闭,这和是否支持支持HOLD_CURSORS_OVER_COMMIT 无关。
             四 验证数据库是否支持ResultSet的各种特性
        不同的数据库版本及 JDBC 驱动版本,对 ResultSet 的各种高级特性的支持是不一样的,我们可以通过以下方法,来验证具体的数据库及 JDBC 驱动,是否支持 ResultSet 的各种特性。
             DatabaseMetaData dbMeta = conn.getMetaData();  
              然后调用 DatabaseMetaData 对象的以下方法:  
               boolean supportsResultSetType(int resultSetType);  
               boolean supportsResultSetConcurrency(int type, int concurrency);  
               boolean supportsResultSetHoldability(int holdability);
            参考的2 篇英文文档:  
         http://cs.fELK.cvut.cz/10gr2/java.102/b14355/jdbcvers.htm (JDBC Standards Support )  
         http://download.oracle.com/docs/cd/B10501_01/java.920/a96654/resltset.htm#1023642 (Oracle9i JDBC Developer"s Guide and Reference Release 2 (9.2))
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2025-2-26 07:20 , Processed in 0.567115 second(s), 50 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表