MySQL 的 JDBC ResultSet 忽略 ResultSet 类型

M.S*_*sek 5 java mysql jdbc resultset

我正在尝试在 Java 应用程序中处理大量数据。数据存储在MySQL数据库中,我使用jdbc连接器8.0.11。

我的问题是我需要多次访问每条记录并且再次执行查询需要太多时间。使用ResultSet.absolute(1)会引发异常,解释游标为 TYPE_FORWARD_ONLY。

如此处所述,应创建带有参数ResultSet.TYPE_SCROLL_INSENSITIVE和参数的语句ResultSet.CONCUR_READ_ONLY,以便获得具有滚动能力的结果集。

但我的创建ResultSet始终是ResultSet.TYPE_FORWARD_ONLY,忽略创建语句方法中提供的任何参数。

在MySQL官方网站中,我没有找到任何解释或信息是否支持此功能。

对于测试用例,我编写了这段代码来检查其他组合是否会影响ResultSet类型并且总是得到TYPE_FORWARD_ONLY.

Connection conn = Database.getConnection();
    Statement st = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
    if(st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
        System.out.println("Should be scroll sensitive, is forward only");
    }
    st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
    if(st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
        System.out.println("Should be scroll insensitive, is forward only");
    }
    st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
    if(st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
        System.out.println("Should be scroll insensitive, is forward only");
    }
    st = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);
    if(st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
        System.out.println("Should be scroll sensitive, is forward only");
    }
    st = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY);
    if(st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
        System.out.println("Should be scroll sensitive, is forward only");
    }
    st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE,ResultSet.HOLD_CURSORS_OVER_COMMIT);
    if(st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
        System.out.println("Should be scroll insensitive, is forward only");
    }
    st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY,ResultSet.HOLD_CURSORS_OVER_COMMIT);
    if(st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
        System.out.println("Should be scroll insensitive, is forward only");
    }
    st = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE,ResultSet.HOLD_CURSORS_OVER_COMMIT);
    if(st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
        System.out.println("Should be scroll sensitive, is forward only");
    }       
    st = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_READ_ONLY,ResultSet.HOLD_CURSORS_OVER_COMMIT);
    if(st.getResultSetType() == ResultSet.TYPE_FORWARD_ONLY) {
        System.out.println("Should be scroll sensitive, is forward only");
    }
Run Code Online (Sandbox Code Playgroud)

这是解释如何创建数据库连接的代码片段:

private static final String driverName = "com.mysql.cj.jdbc.Driver";

    com.mysql.cj.jdbc.Driver dr = (com.mysql.cj.jdbc.Driver) Class.forName(driverName).newInstance();

    MysqlDataSource src = new MysqlDataSource();
    src.setUseCursorFetch(true);        
    src.setServerName("localhost");     
    src.setPort(port);
    src.setDatabaseName("dbname");
    src.setUseSSL(false);
    src.setUser(dbUser);
    src.setPassword(dbPass);
    src.setServerTimezone("GMT+2");
    conn = src.getConnection(dbUser, dbPass);
Run Code Online (Sandbox Code Playgroud)

所以我想问:

  1. 为什么我的ResultSet总是TYPE_FORWARD_ONLY
  2. 有什么办法可以改变这种行为吗?

dsp*_*ser 1

JDBCResultSet在语义上类似于数据库游标,但并非所有数据库系统(包括 MySQL)都支持游标(见下文)。如果实现了TYPE_SCROLL_SENSITIVE或 ,TYPE_SCROLL_INSENSITIVE这通常意味着 JDBC 驱动程序的目标是支持可滚动游标的数据库。当然,仍然可以编写 JDBC 驱动程序来通过缓存结果集来模拟此行为,但大多数驱动程序不这样做。

来自MySQL文档((src: https: //dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-implementation-notes.html

MySQL 不支持 SQL 游标,并且 JDBC 驱动程序不模拟它们,因此 setCursorName() 不起作用。

新版本的 MySQL 确实部分支持游标(http://www.mysqltutorial.org/mysql-cursor/),但它们仍然不可滚动。

因此,要做你想做的事,只需缓存结果集(例如将其存储在哈希映射或其他容器中)并在需要时检索特定记录。