`

ResultSet.TYPE_SCROLL_SENSITIVE到底发生了什么

 
阅读更多

这个问题我在几年前说过,但今天再次从CSDN上看到有人问这个问题,可以看出,真正懂这个问题的人1%都不到。
我再次把这个问题写在这里,希望光临我的BLOG的人能真正了解它。

我们先来做一个例子,在例子中我用的是mysql-essential-5.1.30-win32版。

来跟我做以下几个命令:

mysql> create database axman;
mysql> use axman;
mysql> create table axmantest(
    -> id int(4) not null auto_increment primary key
    -> name varchar(20));

mysql> insert into axmantest (name) values ('axman')
mysql> insert into axmantest (name) values ('sager')
mysql> insert into axmantest (name) values ('p4');

OK,写一个测试程序:
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;


public class MainTest {
 public static void main(String[] args) throws Exception{
  
  Class.forName("org.gjt.mm.mysql.Driver");
  Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/axman?useUnicode=true&characterEncoding=UTF-8","root","password");
  Statement stmt = conn.createStatement(ResultSet.CONCUR_UPDATABLE, ResultSet.TYPE_SCROLL_SENSITIVE);
  ResultSet rs = stmt.executeQuery("select * from axmantest");
  System.out.println("请删除!");
  Thread.sleep(1000*20);
  while(rs.next()){
   System.out.println(rs.getString(1)+","+rs.getString(2));
  }
  rs.close();
  stmt.close();
  conn.close();
 }
}

先在刚才的MYSQL命令环境下输入命令:
select * from axmantest;
+----+-------+
| id | name  |
+----+-------+
|  1 | axman |
|  2 | sager |
|  3 | p4    |
+----+-------+
3 rows in set (0.00 sec)

delete from axmantest where id = 3;不要提交,敲好放在这儿,运行那个测试程序。看到“请删除”三个字立即切换到
Mysql命令环境下回车。
跟着:
select * from axmantest;
+----+-------+
| id | name  |
+----+-------+
|  1 | axman |
|  2 | sager |
+----+-------+
2 rows in set (0.00 sec)

回到测试程序,看看:
1,axman
2,sager
3,p4

我的个神啦,这哪叫结果集敏感啊?完全是INSENSITIVE嘛!


但是,这正是TYPE_SCROLL_SENSITIVE造成的。

对于TYPE_SCROLL_INSENSITIVE,一次查询的结果可能存在数据库端的内存缓冲中,也可以直接发送到JVM的内存中,
如果结果集很小,会直接发送到JVM层,然后被next定位,转换数据类型,显示,或者缓存在数据库内存中。总之
查询结果已经和数据库脱离,这时如果数据库记录被其它进程更新,则结果集无法得知,还是使用缓存的记录。

而对于TYPE_SCROLL_SENSITIVE,一次查询的结果并不是直接的记录被缓存下来,只是符合条件的记录的“原始ROWID”
被缓存了,这个原始ROWID并非特指ORACLE的ROWID,而是数据库底层定位记录的索引值。简单说
select * from axmantest操作的结果并不是
1,axman
2,sager
3,p4
这些内容被缓存了。而是类似rd_file_offset_0x111010101001这样的值被缓存了,然后next定位到这条记录时,
数据库会再次根据这个ROWID做底层操作:
select * from axmantest where rowid = rd_file_offset_0x111010101001;
简单说每next一次都会发生一次查询,这样可以保证next后操作到的是当前最新的数据。
对于更新操作,如果你先查询,然后数据被其它进程更新掉了,然后next到这条记录时肯定没有问题,会取出最新的
内容,但对于删除操作。因为数据库删除记录只是记录上做一个标记,不再被检索,但原来被缓存的ROWID还在,根据
它还可以通过数据库自己的底层操作正确地把数据提取出来,所以你看到的已经被手工删除的数据又被显示出来了。

同样插入操作因为查询的时候结果集中还没有要插入的操作,所以不可能缓存了它的ROWID,我们再次做这个例子,把
“请删除”修改成“请插入”(有些不好听),现在数据库中是两条记录,当运行程序看到“请插入”时立即插入,注意
我说的是往表中插入记录,不是插入别的。然后看一下运行结果还是两条记录。

如果有兴趣再试一下更新操作,你会看更新的结果会马上反映出来。

所以TYPE_SCROLL_SENSITIVE只能更新操作敏感,其它的插入操作和删除操作不会及时地反映到结果集中。

分享到:
评论

相关推荐

    javaResultSet常用方法.pdf

    其中,resultSetType指定ResultSet的类型,可以是ResultSet.TYPE_FORWARD_ONLY、ResultSet.TYPE_SCROLL_INSENSITIVE或ResultSet.TYPE_SCROLL_SENSITIVE之一。resultSetConcurrency指定ResultSet的并发类型,可以是...

    采用JDBC进行数据库分页查询

    // ResultSet.TYPE_SCROLL_SENSITIVE:可滚动。当其他用户更改数据库时这个记录也会改变。 // 能否更新记录: // ResultSet.CONCUR_READ_ONLY,只读 // ResultSet.CONCUR_UPDATABLE,可更新 PreparedStatement pstat =...

    java resultset常用方法

    - **resultSetType**:定义ResultSet的类型,可以是`ResultSet.TYPE_FORWARD_ONLY`、`ResultSet.TYPE_SCROLL_INSENSITIVE`或`ResultSet.TYPE_SCROLL_SENSITIVE`。 - **resultSetConcurrency**:定义ResultSet的并发...

    Db.rar_滚动

    对于大结果集,通常使用`ResultSet.TYPE_SCROLL_SENSITIVE`或`ResultSet.TYPE_SCROLL_INSENSITIVE`来创建可滚动的结果集,前者对数据库的修改敏感,后者不敏感。 5. **分页和数据流**:在处理大量数据时,数据滚动...

    JDBCJDBC高级应用

    - 创建可更新结果集时,需要指定并发性类型,如 `ResultSet.CONCUR_UPDATABLE`,并配合 `ResultSet.TYPE_SCROLL_INSENSITIVE` 或 `ResultSet.TYPE_SCROLL_SENSITIVE` 使用。 - 更新结果集中的数据通常涉及 `update...

    jdbc各种数据库连接

    Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); // 执行SQL查询 String sql = "select * from test"; ResultSet rs = stmt.executeQuery(sql); ``` 在这...

    几种常用数据库的连接 mysql sql server oracle

    Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); String sql = "select * from TestTable"; ResultSet rs = stmt.executeQuery(sql); while (rs.next())...

    《Java程序设计案例教程》教学课件09Java数据库编程.pptx

    ResultSet.TYPE_SCROLL_SENSITIVE则在移动时会反映数据库的最新状态。resultSetConcurrency的ResultSet.CONCUR_READ_ONLY意味着结果集是只读的,不能用于更新,而ResultSet.CONCUR_UPDATABLE则允许对结果集进行修改...

    jsp连接数据库

    其中,`ResultSet.TYPE_SCROLL_SENSITIVE` 表示结果集可滚动且对数据表的更改敏感,`ResultSet.CONCUR_UPDATABLE` 表示结果集支持更新操作。 4. **备选方案** 除了使用 JTDs 驱动之外,文档中还给出了另外两种...

    ResultSet剖析

    - `resultSetType`:设置`ResultSet`的滚动模式,`ResultSet.TYPE_FORWARD_ONLY`表示仅支持前向滚动,`ResultSet.TYPE_SCROLL_INSENSITIVE`和`ResultSet.TYPE_SCROLL_SENSITIVE`则允许双向滚动,区别在于后者对数据...

    只进结果集不支持请求的操作的“解决方法

    Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); ``` 在这里,`ResultSet.TYPE_SCROLL_SENSITIVE`表示结果集是可滚动的,并且对外部更改敏感;`...

    jsp中各种连接数据库方式

    ### JSP 中连接数据库的各种方式 在 Java Server Pages (JSP) 技术中,连接数据库是实现动态网站的关键步骤之一。... Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet...

    jsp连接各种数据库代码及读取数据实例

    Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); String sql="select * from test"; ResultSet rs=stmt.executeQuery(sql); while(rs.next()) { %> 您的第一个...

    连接数据库大全

    Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); String sql = "select * from test"; ResultSet rs = stmt.executeQuery(sql); ``` 5. **处理查询结果...

    JSP中访问数据库大全

    Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); String sql = "select * from test"; ResultSet rs = stmt.executeQuery(sql); ``` 4. 遍历结果集并显示...

    java 连接数据库代码大全

    Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); String sql = "select * from test"; ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { %>...

    在JSP中连接各种数据库

    Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); String sql = "SELECT * FROM test"; ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { ...

    jsp连接各种数据库

    Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); String sql = "select * from test"; ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { %>...

Global site tag (gtag.js) - Google Analytics