当前位置: 首页 > 面试题库 >

MySQL ResultSet可滚动/可更新无法按预期工作

江高飞
2023-03-14
问题内容

我有一个测试JDBC程序,该程序试图更改ResultSet的可滚动性和可更新性功能。不幸的是,所有组合TYPE_,并CONCUR_似乎产生相同的结果(TYPE_SCROLL_INSENSITIVECONCUR_READ_ONLY)。

即使使用默认值(TYPE_FORWARD_ONLY),也可以在ResultSet中滚动。谁能解释为什么?

我正在使用MySQL 5.6和JDK7。这是代码:

public class ResultSetTest3 {

    public static void main(String[] args)
    {
        Connection conn;

        try {
            conn = DriverManager.getConnection("jdbc:mysql://localhost/bd", "user", "password");

            Statement sta = conn.createStatement();
            sta.execute("DELETE FROM test");
            sta.close();

            PreparedStatement ps = conn.prepareStatement("INSERT INTO test VALUES(?, ?)");
            for(int i=1; i<=100; i++)
            {
                ps.setInt(1, i);
                ps.setString(2, "Teste " + i);
                ps.addBatch();
            }
            ps.executeBatch();
            ps.close();

            System.out.println("TYPE_FORWARD_ONLY  CONCUR_READ_ONLY");
            result(conn, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
            System.out.println("===================================");

            System.out.println("TYPE_SCROLL_INSENSITIVE  CONCUR_READ_ONLY");
            result(conn, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY);
            System.out.println("===================================");

            System.out.println("TYPE_SCROLL_SENSITIVE  CONCUR_READ_ONLY");
            result(conn, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
            System.out.println("===================================");

            System.out.println("TYPE_FORWARD_ONLY  CONCUR_UPDATABLE");
            result(conn, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_UPDATABLE);
            System.out.println("===================================");

            System.out.println("TYPE_SCROLL_INSENSITIVE  CONCUR_UPDATABLE");
            result(conn, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
            System.out.println("===================================");

            System.out.println("TYPE_SCROLL_SENSITIVE  CONCUR_UPDATABLE");
            result(conn, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
            System.out.println("===================================");

            conn.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    private static void result(Connection conn, int type, int update) throws SQLException
    {
        Statement sta = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
        ResultSet rs = sta.executeQuery("SELECT * FROM test");

        System.out.println(rs.getConcurrency() + " " + update);
        System.out.println(rs.getType() + " " + type);

        try
        {
            rs.absolute(10);
            System.out.println(rs.getInt(1) + " - " + rs.getString(2));

            rs.relative(20);
            System.out.println(rs.getInt(1) + " - " + rs.getString(2));

            rs.previous();
            System.out.println(rs.getInt(1) + " - " + rs.getString(2));

            rs.first();
            System.out.println(rs.getInt(1) + " - " + rs.getString(2));

            try {
                System.out.println("AGORA!!!");
                Thread.sleep(20000);
            } catch (Exception e) {
                System.out.println(e);
            }
            rs.absolute(3);
            System.out.println(rs.getInt(1) + " - " + rs.getString(2));
        }
        catch(SQLException e)
        {
            System.out.println("Not Scrollable");
        }

        try
        {
            rs.next();
            rs.next();
            rs.next();
            rs.next();

            rs.deleteRow();

            rs.next();
            rs.updateString(2, "TesteUpdate");

            rs.insertRow();
        }
        catch(SQLException e)
        {
            System.out.println("Not Updatable");
        }

        rs.close();
        sta.close();
    }
}

问题答案:

正如马克Rotteveel到问题的评论中提到,MySQL的高速缓存默认的ResultSet数据(也由Ben J.
Christensen的一篇博客文章中讨论这里)。这种缓存的明显副作用是MySQL Connector / J将“升级”
TYPE_FORWARD_ONLY ResultSet使其实际上是可滚动的:

Statement s = dbConnection.createStatement(
        ResultSet.TYPE_FORWARD_ONLY, 
        ResultSet.CONCUR_READ_ONLY);
ResultSet rs = s.executeQuery("SELECT * FROM testdata");
rs.last();
System.out.println(String.format("Current row number: %d", rs.getRow()));
rs.previous();
System.out.println(String.format("Current row number: %d", rs.getRow()));

显示

Current row number: 3
Current row number: 2

根据上面引用的博客文章,防止缓存和“流式处理” ResultSet数据的方法是使用Statement.setFetchSize

Statement s = dbConnection.createStatement(
        ResultSet.TYPE_FORWARD_ONLY, 
        ResultSet.CONCUR_READ_ONLY);
s.setFetchSize(Integer.MIN_VALUE);
ResultSet rs = s.executeQuery("SELECT * FROM testdata");
rs.next();
System.out.println("Data from first row: " + rs.getString(2));
System.out.println("now let's try rs.last() ...");
try {
    rs.last();
    System.out.println("... Okay, done.");
} catch (Exception e) {
    System.out.println("... Exception: " + e.getMessage());
}

导致

Data from first row: Gord
now let's try rs.last() ...
... Exception: Operation not supported for streaming result sets


 类似资料:
  • 问题内容: 我正在使用selenium来抓取一些数据。 我单击的页面上有一个按钮,说“ custom_cols”。此按钮为我打开一个窗口,从中可以选择列。 此新窗口有时需要一些时间才能打开(大约5秒钟)。所以我已经使用了 延迟为20秒。但是有时它无法在新窗口中选择查找元素,即使该元素可见。在其余时间中,这种情况仅发生十次一次。 我在其他地方也使用了相同的功能(WebDriverWait),并且可以

  • 问题内容: 经过测试后,我只能对已经解析过的JSON数据返回一个肯定值。 根据官方文件: isValidJSONObject返回一个布尔值,该布尔值指示是否可以将给定对象转换为JSON数据。 但是,尽管事实是我尝试将其从JSON转换为NSDictionary的对象都可以正常转换,但仍会返回。 这是我的代码: 我的日志包含以下内容: 然后是dict的输出,这是一个巨大的NSMutableDictio

  • 问题内容: 考虑以下可以在任何程序执行之前预加载的库: 问题是,尽管总是调用全局变量的构造函数,但对于某些程序却不调用析构函数,例如: 对于其他一些程序,按预期方式调用析构函数: 您能解释一下为什么在第一种情况下不调用析构函数吗?编辑:上面的问题已得到解答,即程序可能会使用_exit(),abort()退出。 然而: 有没有办法在预加载的程序退出时强制调用给定函数? 问题答案: 具有作为其初始化代

  • 我必须将日期-时间字符串转换为分区日期-时间对象。我使用DateTimeForman读取模式。根据留档,模式中的“Z”可以接受以下格式: /-0000 但是“分区约会”。parse(myDate,formatter)只适用于第一种情况;相反,在第二种情况下,代码生成一个异常。 我用的是8Java 我做错什么了?谢谢!

  • 我编写了自己的AtomicDouble类,还有一个BankAccount类,它执行两个简单的取款和存款操作,它有一个AtomicDouble实例(余额)。我的代码的问题是,当我在deposit()中调用addAndGet方法时,程序会陷入一个无限循环,compareAndSet()永远不会返回真值,但当我调试它时,currentValue和atomic中的值。get()相等,但此方法无法理解。 有

  • 我有一个Log4j2.xml定义为: 据我所知,当我的日志文件达到1MB时,它应该会滚动到新的日志文件。要滚动的文件数应为30。然而,如果你看看我下面的日志,有超过40个,所有最新的都接近30MB。当前日志文件MLMServices。日志记录了从2016年4月13日至今的条目。事实上,最后几个日志文件是MLMServices-2016-05-24-4。日志,MLMServices-2016-05-