JDBC 具有 MySQL 的结果集忽略结果集类型
JDBC ResultSet with MySQL ignores ResultSet type
我正在尝试处理 Java 应用程序中的大量数据。数据存储在 MySQL 数据库中,我正在使用 jdbc 连接器 8.0.11.
我的问题是我需要多次访问每条记录并且再次执行查询需要太多时间。使用 ResultSet.absolute(1)
会抛出异常,说明游标是 TYPE_FORWARD_ONLY.
如 here 所述,应使用参数 ResultSet.TYPE_SCROLL_INSENSITIVE
和 ResultSet.CONCUR_READ_ONLY
参数创建语句以获得具有滚动能力的结果集。
但我创建的 ResultSet
总是 ResultSet.TYPE_FORWARD_ONLY
,忽略了创建语句方法中提供的任何参数。
在官方中MySQL site我没有找到任何解释或信息是否支持此功能。
对于测试用例,我编写了这段代码来检查其他组合是否会影响 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");
}
这里是解释我如何创建数据库连接的代码片段:
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);
所以想请教一下:
- 为什么我的
ResultSet
总是 TYPE_FORWARD_ONLY
?
- 有什么办法可以改变这种行为吗?
A JDBC ResultSet
在语义上类似于 数据库游标 但并非所有数据库系统(包括 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 does not support SQL cursors, and the JDBC driver does not
emulate them, so setCursorName() has no effect.
MySQL 的新版本确实部分支持游标 (http://www.mysqltutorial.org/mysql-cursor/),但它们仍然不可滚动。
因此,要执行您想要的操作,只需缓存结果集(例如,将其存储在哈希映射或其他容器中)并在需要时检索特定记录。
我正在尝试处理 Java 应用程序中的大量数据。数据存储在 MySQL 数据库中,我正在使用 jdbc 连接器 8.0.11.
我的问题是我需要多次访问每条记录并且再次执行查询需要太多时间。使用 ResultSet.absolute(1)
会抛出异常,说明游标是 TYPE_FORWARD_ONLY.
如 here 所述,应使用参数 ResultSet.TYPE_SCROLL_INSENSITIVE
和 ResultSet.CONCUR_READ_ONLY
参数创建语句以获得具有滚动能力的结果集。
但我创建的 ResultSet
总是 ResultSet.TYPE_FORWARD_ONLY
,忽略了创建语句方法中提供的任何参数。
在官方中MySQL site我没有找到任何解释或信息是否支持此功能。
对于测试用例,我编写了这段代码来检查其他组合是否会影响 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");
}
这里是解释我如何创建数据库连接的代码片段:
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);
所以想请教一下:
- 为什么我的
ResultSet
总是TYPE_FORWARD_ONLY
? - 有什么办法可以改变这种行为吗?
A JDBC ResultSet
在语义上类似于 数据库游标 但并非所有数据库系统(包括 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 does not support SQL cursors, and the JDBC driver does not emulate them, so setCursorName() has no effect.
MySQL 的新版本确实部分支持游标 (http://www.mysqltutorial.org/mysql-cursor/),但它们仍然不可滚动。
因此,要执行您想要的操作,只需缓存结果集(例如,将其存储在哈希映射或其他容器中)并在需要时检索特定记录。