`

jdbc ResultSet分析

阅读更多
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



程序如下:

Java代码 
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() + "]\t" + rs.getString(1) + "\t" + rs.getString(2)  
                        + "\t" + rs.getString(3));  
                Thread.sleep(20000);  
            }  
              
            rs.close();  
            stmt.close();  
        } catch (SQLException e) {  
            e.printStackTrace();  
        } finally {  
            try {  
                conn.close();  
            } catch (Exception e) {  
            }  
        }  
    } 

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() + "]\t" + rs.getString(1) + "\t" + rs.getString(2)
+ "\t" + rs.getString(3));
Thread.sleep(20000);
}

rs.close();
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
conn.close();
} catch (Exception e) {
}
}
}


定义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);



分享到:
评论

相关推荐

    Jdbc深入分析

    ### Jdbc深入分析 #### 一、JDBC概述与应用场景 **1.1 JDBC概念** JDBC(Java Database Connectivity)是Java中用来对关系型数据库进行访问的一种标准API,它提供了一种统一的方式去访问不同的数据库系统。通过...

    基于java的jdbc的效率分析

    理解JDBC的效率分析至关重要,因为它直接影响到应用程序的性能和资源利用率。 首先,我们要明白JDBC的基本工作流程。它包括以下步骤: 1. 加载驱动:程序通过`Class.forName()`方法加载对应的数据库驱动。 2. 获取...

    小白看得懂的MySQL JDBC 反序列化漏洞分析 - 先知社区1

    【MySQL JDBC 反序列化漏洞分析】 MySQL JDBC 反序列化漏洞主要涉及到Java数据库连接(JDBC)驱动程序中的安全问题。JDBC是Java中用于与数据库交互的标准接口,允许开发者使用Java语言执行SQL语句。在特定版本的...

    jdbc.zip_java jdbc_java+jdbc_jdbc_jdbc Java_zip

    Java JDBC(Java Database Connectivity)是Java编程语言中用于与各种关系...通过分析和理解这两个源文件,我们可以学习到如何在Java应用程序中使用JDBC进行数据库交互,以及如何设计和实现简单的客户端-服务器通信。

    hive jdbc依赖的jar包

    在实际应用中,Hive JDBC常用于ETL(提取、转换、加载)过程,数据分析,或者作为大数据应用的后端数据源。例如,Web应用程序可能通过Hive JDBC与Hive交互,进行大数据的实时分析和报表生成。 需要注意的是,由于...

    多线程以JDBC的方式返回海量数据

    对于多线程处理,每个线程可以拥有自己的`Statement`或`ResultSet`对象。为了避免线程之间的数据竞争,我们需要确保每个线程只操作它自己的数据,或者使用数据库提供的事务支持来确保数据的一致性。 以下是一个基本...

    impala数据库JDBC驱动集

    在大数据分析场景下,Impala的JDBC驱动使得Java应用程序能够无缝集成到Hadoop环境,提供高效、低延迟的分析能力。这对于需要实时洞察业务数据的企业来说,具有极大的价值。同时,由于JDBC的标准化,开发者可以利用...

    ResultSet用法集锦

    本文将深入探讨`ResultSet`的使用方法,结合源码分析和实用工具,以帮助你更好地理解和应用这个重要的数据处理组件。 1. `ResultSet`接口概述: `ResultSet`接口是Java JDBC(Java Database Connectivity)的一部分...

    poi根据ResultSet到处Excle源码

    3. **ResultSet**:这是Java JDBC接口,用于存储和检索SQL查询结果。 4. **Excle**:这里是目标输出格式,即Microsoft Excel文件,通常用于数据分析和报告。 这个项目可能涉及的知识点包括: - Java基础语法和面向...

    Hive_JDBC.zip_hive java_hive jdbc_hive jdbc pom_java hive_maven连

    Hive JDBC(Java Database Connectivity)是Hive提供的一种接口,使得其他编程语言,如Java,能够通过JDBC驱动程序与Hive进行交互,实现数据查询、分析和操作。本教程将深入讲解如何使用Hive JDBC在Java项目中建立与...

    hive-jdbc-uber-2.6.5.0-292.zip

    例如,Web应用程序、ETL工具、数据分析平台等,都可以利用Hive JDBC与Hive进行数据交互,从而发挥Hadoop集群的计算能力。 总结,Hive JDBC Uber Jar是Java开发者连接Hive的重要工具,它简化了依赖管理,提高了代码...

    jdbc 源码 oracle 自带jdbc

    源码分析主要涉及以下几个核心组件: 1. `Driver`接口:所有JDBC驱动都必须实现这个接口,注册到JDBC DriverManager中,以便于应用程序通过`Class.forName()`加载和使用。 2. `Connection`接口:表示与数据库的...

    使用log4jdbc更有效的记录java sql日志.docx

    Log4jdbc 是一个非常实用的 Java SQL 日志框架,它通过代理模式来拦截常见的 JDBC 驱动,如 Oracle、Derby、MySQL、PostgreSQL、H2、HSQLDB 等,使得开发者能够轻松地记录和分析 SQL 操作。这个框架的核心优势在于其...

    Mysql JDBC源码 官网版

    4. `com.mysql.jdbc.ResultSet`:实现了JDBC的`java.sql.ResultSet`接口,对MySQL查询结果进行封装。 源码分析可以深入了解以下关键点: 1. 数据库连接建立:`Driver.connect()`方法是如何根据URL和配置信息建立...

    clickhouse-jdbc(从0.2.4到0.3.2版本).zip

    2. **JDBC接口**:点击house-JDBC遵循JDBC规范,提供`java.sql.Connection`, `Statement`, `PreparedStatement`和`ResultSet`等接口,使得Java开发者可以使用熟悉的API进行数据库操作。例如,你可以创建连接(`...

    ClickHouse-JDBCJar包.zip

    总的来说,"ClickHouse-JDBCJar包.zip"提供了Java应用程序与ClickHouse数据库之间的桥梁,使得Java开发者能够利用强大的ClickHouse列式存储能力,高效地进行大数据分析和处理。结合列式存储的优势,ClickHouse与Java...

    greenplum数据库jdbc驱动下载

    在实际开发中,使用Greenplum JDBC驱动,首先需要将其添加到项目类路径中,然后通过`DriverManager.getConnection()`方法建立连接,使用`Statement`或`PreparedStatement`对象执行SQL,最后通过`ResultSet`对象处理...

    greenplum_jdbc_5.1.4.zip

    《Greenplum JDBC驱动5.1.4详解》 在大数据处理领域,Greenplum数据库以其优秀的并行处理能力和大规模数据存储能力而受到广泛关注。为了方便Java开发者与Greenplum数据库进行交互,Pivotal公司提供了Greenplum JDBC...

    vertica jdbc driver 驱动下载

    Vertica JDBC Driver是一款由Vertica公司提供的Java数据库连接器,用于在Java应用程序中与Vertica分析平台进行交互。它遵循Java Database Connectivity (JDBC) API标准,为开发人员提供了访问和操作Vertica数据库的...

    尚硅谷jdbc视频教程

    4. **性能瓶颈**:分析SQL语句执行计划,优化索引设计,使用更高效的查询方式。 #### 七、尚硅谷JDBC视频教程的特点 尚硅谷提供的JDBC视频教程非常适合初学者学习,它不仅覆盖了JDBC的基本概念和核心API的使用方法...

Global site tag (gtag.js) - Google Analytics