DatabaseMetaData.ownDeletesAreVisible vs DatabaseMetaData.deletesAreDetected 争议
DatabaseMetaData.ownDeletesAreVisible vs DatabaseMetaData.deletesAreDetected Controversy
我正在使用 JDBC 和 mysql-connector-java-6.0.2.jar,除非我做错了什么,否则我认为 DatabaseMetaData.ownDeletesAreVisible 和 DatabaseMetaData.deletesAreDetected 实现在某种程度上彼此不一致。
以下是 JDBC 规范关于 ownDeletesAreVisible 的说明:
"...如果删除的行被删除或替换为空行,方法DatabaseMetaData.ownDeletesAreVisible(int类型)将return为真。它return如果 ResultSet 对象仍然包含已删除的行,则为 false,这意味着删除对于给定类型的 ResultSet 对象的更改是不可见的..."
关于 deletesAreDetected:
"...方法 deletesAreDetected returns false 如果从 ResultSet 对象中删除的行已从中删除,如果删除的行被空行或无效行替换则为 true ..."
我将输出添加为注释:
import static java.sql.ResultSet.CONCUR_UPDATABLE;
import static java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
import java.sql.*;
public class Deletions {
public static void main(String[] args) throws SQLException {
try (Connection conn = DBUtils.getConnection();
Statement stmt = conn.createStatement(TYPE_SCROLL_INSENSITIVE, CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("select * from book")) {
DatabaseMetaData dbmd = conn.getMetaData();
//prints false
System.out.println(dbmd.ownDeletesAreVisible(TYPE_SCROLL_INSENSITIVE));
// prints false. Controversy?
System.out.println(dbmd.deletesAreDetected(TYPE_SCROLL_INSENSITIVE));
// Prints everything including foo
printAll(rs);
// deletes foo
while (rs.next()) {
String title = rs.getString(2);
if (title.equalsIgnoreCase("foo")) {
rs.deleteRow();
}
}
// Prints everything without foo
printAll(rs);
}
}
private static void printAll(ResultSet rs) throws SQLException {
rs.beforeFirst();
while (rs.next()) {
System.out.println(rs.getString(2));
}
rs.beforeFirst();
}
}
这并不矛盾,JDBC 4.2 specification,第 15.2.4.2 节说(强调我的):
After the method deleteRow
has been called, the current row is deleted in the underlying data source. This deletion is visible as a change in the open ResultSet
object if the row is either removed or replaced by an empty or invalid row.
If the deleted row is removed or replaced by an empty row, the method
DatabaseMetaData.ownDeletesAreVisible(int type)
will return true
. It
returns false
if the ResultSet
object still contains the deleted row, which means that the deletion is not visible as a change to ResultSet objects of the given type.
[..]
If a ResultSet
object can detect deletions, the ResultSet
method rowDeleted
returns true when the current row has been deleted and false when it has not. However, rowDeleted
also returns false
if the ResultSet object cannot detect deletions. The method DatabaseMetaData.deletesAreDetected(int type)
can be called to see whether a ResultSet
object of the specified type can call the method rowDeleted
to detect a deletion that is visible. The method deletesAreDetected
returns false
if a row deleted from the ResultSet
object is removed from it and true if the deleted row is replaced by an empty or invalid row.
字里行间需要阅读一些内容(并查看该部分中的示例代码),但这意味着 deletesAreDetected
只有 才有意义,如果删除是可见的,它辨别如何删除是可见的:该行已被删除(false
),或者被空行或无效行替换(true
) .
因此 ownDeletesAreVisible
returns false
,deletesAreDetected
的结果对于 'own' 删除没有任何意义(除了 'deletes are not detected');它可能对 'others' 删除有意义,但我怀疑其他删除是否可见,而您自己的删除不可见。
我的结论:
- 使用MYSQL:
dbmd.ownDeletesAreVisible(TYPE_SCROLL_INSENSITIVE) 返回错误:
"...如果 ResultSet 对象仍然包含已删除的行,则 return 为 false..."
dbmd.deletesAreDetected(TYPE_SCROLL_INSENSITIVE) 返回错误:
"...returns false 如果从 ResultSet 对象中删除的行已从中删除..."
结果:
ResultSet rs = stmt.executeQuery("select * from book");
printAll(rs); // Prints everything including foo
// deletes foo
while (rs.next()) {
String title = rs.getString(2);
if (title.equalsIgnoreCase("foo")) {
rs.deleteRow();
}
}
printAll(rs); // Prints everything without foo. Makes no sense.
- 使用 Apache Derby 数据库:
dbmd.ownDeletesAreVisible(TYPE_SCROLL_INSENSITIVE) 返回真值:"...如果删除的行被删除或替换为空行,该方法将 return真的..."
dbmd.deletesAreDetected(TYPE_SCROLL_INSENSITIVE) 返回真值:“...如果删除的行被空行或无效行替换,该方法将 return 真...”。 =12=]
结果:
ResultSet rs = stmt.executeQuery("select * from book");
printAll(rs); // Prints everything including foo
// deletes foo
while (rs.next()) {
String title = rs.getString(2);
if (title.equalsIgnoreCase("foo")) {
rs.deleteRow();
}
}
/* Prints 'null' instead of 'foo' here. Now this makes sense */
printAll(rs);
结论:
此 MySQL 实施未正确遵守 JDBC 规范。上述两种方法相互矛盾,也与输出相矛盾。
Apache Derby DB 正确实现了 JDBC 规范。
我正在使用 JDBC 和 mysql-connector-java-6.0.2.jar,除非我做错了什么,否则我认为 DatabaseMetaData.ownDeletesAreVisible 和 DatabaseMetaData.deletesAreDetected 实现在某种程度上彼此不一致。
以下是 JDBC 规范关于 ownDeletesAreVisible 的说明:
"...如果删除的行被删除或替换为空行,方法DatabaseMetaData.ownDeletesAreVisible(int类型)将return为真。它return如果 ResultSet 对象仍然包含已删除的行,则为 false,这意味着删除对于给定类型的 ResultSet 对象的更改是不可见的..."
关于 deletesAreDetected:
"...方法 deletesAreDetected returns false 如果从 ResultSet 对象中删除的行已从中删除,如果删除的行被空行或无效行替换则为 true ..."
我将输出添加为注释:
import static java.sql.ResultSet.CONCUR_UPDATABLE;
import static java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE;
import java.sql.*;
public class Deletions {
public static void main(String[] args) throws SQLException {
try (Connection conn = DBUtils.getConnection();
Statement stmt = conn.createStatement(TYPE_SCROLL_INSENSITIVE, CONCUR_UPDATABLE);
ResultSet rs = stmt.executeQuery("select * from book")) {
DatabaseMetaData dbmd = conn.getMetaData();
//prints false
System.out.println(dbmd.ownDeletesAreVisible(TYPE_SCROLL_INSENSITIVE));
// prints false. Controversy?
System.out.println(dbmd.deletesAreDetected(TYPE_SCROLL_INSENSITIVE));
// Prints everything including foo
printAll(rs);
// deletes foo
while (rs.next()) {
String title = rs.getString(2);
if (title.equalsIgnoreCase("foo")) {
rs.deleteRow();
}
}
// Prints everything without foo
printAll(rs);
}
}
private static void printAll(ResultSet rs) throws SQLException {
rs.beforeFirst();
while (rs.next()) {
System.out.println(rs.getString(2));
}
rs.beforeFirst();
}
}
这并不矛盾,JDBC 4.2 specification,第 15.2.4.2 节说(强调我的):
After the method
deleteRow
has been called, the current row is deleted in the underlying data source. This deletion is visible as a change in the openResultSet
object if the row is either removed or replaced by an empty or invalid row.If the deleted row is removed or replaced by an empty row, the method
DatabaseMetaData.ownDeletesAreVisible(int type)
will returntrue
. It returnsfalse
if theResultSet
object still contains the deleted row, which means that the deletion is not visible as a change to ResultSet objects of the given type.[..]
If a
ResultSet
object can detect deletions, theResultSet
methodrowDeleted
returns true when the current row has been deleted and false when it has not. However,rowDeleted
also returnsfalse
if the ResultSet object cannot detect deletions. The methodDatabaseMetaData.deletesAreDetected(int type)
can be called to see whether aResultSet
object of the specified type can call the methodrowDeleted
to detect a deletion that is visible. The methoddeletesAreDetected
returnsfalse
if a row deleted from theResultSet
object is removed from it and true if the deleted row is replaced by an empty or invalid row.
字里行间需要阅读一些内容(并查看该部分中的示例代码),但这意味着 deletesAreDetected
只有 才有意义,如果删除是可见的,它辨别如何删除是可见的:该行已被删除(false
),或者被空行或无效行替换(true
) .
因此 ownDeletesAreVisible
returns false
,deletesAreDetected
的结果对于 'own' 删除没有任何意义(除了 'deletes are not detected');它可能对 'others' 删除有意义,但我怀疑其他删除是否可见,而您自己的删除不可见。
我的结论:
- 使用MYSQL:
dbmd.ownDeletesAreVisible(TYPE_SCROLL_INSENSITIVE) 返回错误: "...如果 ResultSet 对象仍然包含已删除的行,则 return 为 false..."
dbmd.deletesAreDetected(TYPE_SCROLL_INSENSITIVE) 返回错误: "...returns false 如果从 ResultSet 对象中删除的行已从中删除..."
结果:
ResultSet rs = stmt.executeQuery("select * from book");
printAll(rs); // Prints everything including foo
// deletes foo
while (rs.next()) {
String title = rs.getString(2);
if (title.equalsIgnoreCase("foo")) {
rs.deleteRow();
}
}
printAll(rs); // Prints everything without foo. Makes no sense.
- 使用 Apache Derby 数据库:
dbmd.ownDeletesAreVisible(TYPE_SCROLL_INSENSITIVE) 返回真值:"...如果删除的行被删除或替换为空行,该方法将 return真的..."
dbmd.deletesAreDetected(TYPE_SCROLL_INSENSITIVE) 返回真值:“...如果删除的行被空行或无效行替换,该方法将 return 真...”。 =12=]
结果:
ResultSet rs = stmt.executeQuery("select * from book");
printAll(rs); // Prints everything including foo
// deletes foo
while (rs.next()) {
String title = rs.getString(2);
if (title.equalsIgnoreCase("foo")) {
rs.deleteRow();
}
}
/* Prints 'null' instead of 'foo' here. Now this makes sense */
printAll(rs);
结论:
此 MySQL 实施未正确遵守 JDBC 规范。上述两种方法相互矛盾,也与输出相矛盾。
Apache Derby DB 正确实现了 JDBC 规范。