- 浏览: 116511 次
- 性别:
- 来自: 青岛
文章分类
最新评论
-
gozen007:
...
Axis2 与 JAX-WS规范 -
vvnet:
时间长了,好像是沿用了“但是如果preparedStateme ...
oracle preparedStatement ResultSet.Type_Scroll_Insensitive 乱码 -
xdchenggong:
请问你的乱码问题解决了吗,我也遇到这问题了,找不到解决办法
oracle preparedStatement ResultSet.Type_Scroll_Insensitive 乱码 -
623deyingxiong:
补充一点:在Eclipse里,子类的方法名只要满足参数列表,方 ...
overload和override的区别 -
qq274035206:
很好 写的很详细
Eclipse下支持jQuery1.2.6
问题:
我用的数据库是 oracle 字符集 us7ascii
用preparedStatement(sqlString, ResultSet.Type_Scroll_Insensitive, ResultSet.Concur_read_only)
从数据库中 读取数据后 中文字段乱码,不管是转不转码都是乱码
但是如果preparedStatement(sqlString) 转码成GBK后就能正常显示中,服了。
查询百度,有说是oracle jdbc驱动的问题,这个还没有验证,有时间验证一下,作参考。
深入理解(原文http://www.iteye.com/topic/123557 )
JDBC2.0后提出了三种不同的cursor类型,用户代码可以在创建Statement指定cursor类型,如下:
Statement createStatement( int resultSetType, int resultSetConcurrency)
cursor类型
ResultSet.TYPE_FORWARD_ONLY
默认的cursor类型,仅仅支持向前forward,不支持backforward,random,last,first操作,类似单向链表。
TYPE_FORWARD_ONLY类型通常是效率最高最快的cursor类型
ResultSet.TYPE_SCROLL_INSENSITIVE
支持backforward,random,last,first操作,对其它数据session对选择数据做出的更改是不敏感,不可见的。
ResultSet.TYPE_SCROLL_SENSITIVE
支持backforward,random,last,first操作,对其它数据session对选择数据做出的更改是敏感,可见的。
分析
众所周知,JDBC对数据库进行数据查询时,数据库会创建查询结果的cache和cursor。而数据库的cursor是不支持
backforward,random,last,first操作,仅仅只支持向前forward。那么TYPE_SCROLL_INSENSITIVE
是如何实现支持backforward,random,last,first的呢?很简单,TYPE_SCROLL_INSENSITIVE的
Statement查询把所有fetch的记录都缓存到JVM的Resultset对象内,如果有10个记录,直接跳到最后记
录,TYPE_SCROLL_INSENSITIVE方式下把fetch所有记录到jvm端,并缓存下来,再进行random就是在数据库数组里面进行
的。这也是TYPE_FORWARD_ONLY类型通常是效率最高最快的cursor类型原因,如果要做一些复杂的功能,必然是要牺牲一些效率的。
那么为什么TYPE_SCROLL_INSENSITIVE对选择数据做出的更改是不敏感,不可见的呢?前面提到,JDBC对数据库进行数据查询时,数据库会创建查询结果的cache和cursor,如下面sql:
select name,id from foo
用jdbc执行上面的sql语句时,数据库会把foo表所有记录的name和id字段缓存到cache中,之后cache和真正的数据库数据文件没有任何
联系了,foo表发生的改变在查询完成后不会自动同步到cache上去,因此TYPE_SCROLL_INSENSITIVE对选择数据做出的更改是不敏
感,不可见。
那么TYPE_SCROLL_SENSITIVE是怎么做到其它数据session对选择数据做出的更改是敏感,可见的。上面的sql语句用TYPE_SCROLL_SENSITIVE的Statement来执行,会转化成以下的sql语句:
select rowid from foo
数据库这时候是把foo表所有记录的rowid缓存到cache中,用户代码在fetch记录时,再继续做以下查询:
select name,id from foo where rowid=?
因此这时候发生的查询是实时从真正的数据库数据文件中取,因此对期间发生的数据更改是可见的,敏感的。但是这种可见性仅限于update操作,而
insert和delete同样是不可见的。因为如果查询发生在insert之前,insert生成的rowid并不会反应在cache中的rowid结
果集上。在一个记录的rowid已经缓存到cache中,这时候被删除了,但一般数据库的删除是标记删除,也就是说rowid对应那行记录并没有真正从数
据库文件中抹去,一般是可以再次取到记录的。
总结
TYPE_FORWARD_ONLY类型通常是效率最高最快的cursor类型,也是最常用的选择。
TYPE_SCROLL_INSENSITIVE需要在jvm中cache所有fetch到的记录实体,在大量记录集返回时慎用。
TYPE_SCROLL_SENSITIVE在jvm中cache所有fetch到的记录rowid,需要进行二次查询,效率最低,开销最大
JDBC ResultSet分析 (原文http://www.iteye.com/topic/560109 )
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() + "]\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);
参考的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))
评论
发表评论
-
inceptor-sdk-transwarp-6.1.0-SNAPSHOT.jar和weblogic中的antlr*.jar包冲突解决方法
2020-06-29 16:39 728inceptor-sdk-transwarp-6.1.0-S ... -
SPRING TOMCATE 配置正确但后台打印Could not identify the Annotation....
2017-11-29 17:36 1490经过跟踪和分析发现是Axis2的源码中做了判断: pack ... -
log4j.xml警告log4j:WARN The content of element type "log4j:configuration" must ma
2013-09-25 13:05 2552原因log4j.xml中文件的位置不对,顺序为: < ... -
vb6 调用 java webservice 错误之解决
2012-12-17 17:20 4014webservice 是 Axis1.2.1 vb6中使用s ... -
jdk 1.4 多线程池
2012-05-29 16:15 824http://backport-jsr166.sourcefo ... -
使用JDK1.4运行Struts2.0
2011-04-30 14:35 582Struts2.0默认的平台需 ... -
Apache Commons
2011-04-16 18:29 620Components Attributes ... -
difference between Struts 1.x and Struts 2.x
2011-04-16 17:33 892The major difference is that ... -
weblogic 新队列配置
2011-01-14 10:54 1417全部的web服务器,服务器都运行在weblogic.ke ... -
java异常处理之throw, throws,try和catch
2011-01-12 14:07 1851java异常处理之throw, throws,try和ca ... -
MyEclipse 8.6.1主要改进
2011-01-08 21:37 2365MyEclipse 8.6.1下载地址发布了,关注MyEcli ... -
JAVA5的新特性收集
2012-03-30 00:34 719一、java5特性:增强FOR循环 ... -
hibernate 的中文乱码解决办法
2010-03-22 22:36 1113我用 hibernate Synchronizer 时,在 ... -
XMLHTTPRequest对象
2009-11-20 17:21 597XMLHTTPRequest对象 ... -
JAVA开发者最常去的20个英文网站
2009-09-19 23:36 475JAVA开发者最常去的20个 ... -
改变IT世界的11大Apache开源技术
2009-09-19 23:31 916据国外媒体报道,转眼 ... -
Oracle数据库和JSP连接要注意的一些问题
2009-09-19 23:22 946CLOB可用于存放大文本数据,最多可存储4GB数据,在应 ... -
JDK1.4新特性之I/O APIs篇
2009-09-06 23:03 1528当然阅读本文之前,你最好先了解一下原有的Java I/O AP ... -
JDK1.5特性实例
2009-09-06 22:42 889class Temp{ String id =&quo ... -
java面试题大全-基础方面
2009-02-04 17:48 1563Java基础方面: 1、作用 ...
相关推荐
一次只从数据库中查询最大maxCount条记录 ... PreparedStatement pstat = conn.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY); //最大查询到第几条记录.........
对于大结果集,通常使用`ResultSet.TYPE_SCROLL_SENSITIVE`或`ResultSet.TYPE_SCROLL_INSENSITIVE`来创建可滚动的结果集,前者对数据库的修改敏感,后者不敏感。 5. **分页和数据流**:在处理大量数据时,数据滚动...
- 创建可更新结果集时,需要指定并发性类型,如 `ResultSet.CONCUR_UPDATABLE`,并配合 `ResultSet.TYPE_SCROLL_INSENSITIVE` 或 `ResultSet.TYPE_SCROLL_SENSITIVE` 使用。 - 更新结果集中的数据通常涉及 `update...
- `ResultSet.TYPE_SCROLL_INSENSITIVE`:可前后滚动,但对数据库的更改不敏感。 - `ResultSet.TYPE_SCROLL_SENSITIVE`:可前后滚动并能感知数据库的更改,但性能较低。 - `resultSetConcurrency`: - `...
ResultSet.TYPE_SCROLL_INSENSITIVE允许上下移动,但对数据库变化不敏感;ResultSet.TYPE_SCROLL_SENSITIVE则在移动时会反映数据库的最新状态。resultSetConcurrency的ResultSet.CONCUR_READ_ONLY意味着结果集是只读...
- **示例**:`Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY, ResultSet.HOLD_CURSORS_OVER_COMMIT);` #### 四、PreparedStatement类详解 `...
这里,`ResultSet.TYPE_SCROLL_INSENSITIVE`表示结果集对数据库中的变化不敏感,而`ResultSet.CONCUR_READ_ONLY`表示结果集是只读的。如果需要更新结果集,可以使用`ResultSet.CONCUR_UPDATABLE`。 接下来,执行SQL...
8. **可滚动的结果集**: ResultSet对象默认是不可滚动的,但通过设置`ResultSet.TYPE_SCROLL_INSENSITIVE`和`ResultSet.CONCUR_READ_ONLY`,可以创建一个可滚动的结果集,允许前后移动和检查是否已到达结果集的末尾...
创建此类记录集时,需要在创建`Statement`时指定`ResultSet.TYPE_SCROLL_SENSITIVE`或`ResultSet.TYPE_SCROLL_INSENSITIVE`,并设置并发模式(如`ResultSet.CONCUR_READ_ONLY`)。 - 对于`PreparedStatement`,同样...
但在JDBC 2.0中,通过`ResultSet.TYPE_SCROLL_SENSITIVE`和`ResultSet.TYPE_SCROLL_INSENSITIVE`选项,开发者可以创建可滚动的结果集。这使得开发人员可以在结果集中前后移动,甚至直接跳转到特定行。例如,使用`...
然而,通过设置Statement的类型为ResultSet.TYPE_SCROLL_INSENSITIVE或ResultSet.TYPE_SCROLL_SENSITIVE,我们可以获取一个支持滚动的游标。滚动游标允许我们前后移动结果集,不仅可以向上或向下遍历,还可以定位到...
- **游标**:Oracle的游标允许向前和向后滚动的结果集,通过设置`ResultSet.TYPE_SCROLL_INSENSITIVE`和`ResultSet.CONCUR_READ_ONLY`属性。 - **连接池**:使用连接池如C3P0或Apache DBCP,可以有效地管理数据库...
PreparedStatement ps = cn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); ``` 2. **批量更新** - 使用`addBatch()`方法添加多个更新语句到批处理中,然后调用`...
PreparedStatement ps = cn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); ``` 3. **使用`ResultSet`的方法实现记录集的滚动**: ```java rs.absolute(9000); // ...
- **随机访问**:若需实现随机访问,可以创建支持滚动的`Statement`对象,如`stmt=conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY)`。 5. 指针移动 - `ResultSet`的指针...
在Java中,有多种游标类型,如`ResultSet.TYPE_FORWARD_ONLY`(只向前)、`ResultSet.TYPE_SCROLL_INSENSITIVE`(不可感知数据改变的滚动)和`ResultSet.TYPE_SCROLL_SENSITIVE`(可感知数据改变的滚动)。...
然后创建一个PreparedStatement对象,设置游标类型为`ResultSet.TYPE_SCROLL_INSENSITIVE`,并发控制为`ResultSet.CONCUR_READ_ONLY`,以确保结果集的只读性。 - 使用`setMaxRows(startNo+maxCount-1)`限制返回的...
`ResultSet.TYPE_SCROLL_INSENSITIVE`可以在任何位置滚动,但不关心数据变化;`ResultSet.TYPE_SCROLL_SENSITIVE`是敏感模式,可以感知数据的变化。 4. **批量更新**:通过`addBatch()`方法将多条SQL语句添加到...
ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY ); ``` 3. **使用可滚动结果集** - 可以使用`ResultSet`的`absolute`方法来移动游标: ```java ResultSet rs = ...; // 获取结果集 rs....