我正在使用JDBC和mysql-connector-java-6.0.2.jar,除非我做错了什么,我认为DatabaseMetaData.ownDeletesAreVisible和DatabaseMetaData.deletesAreDetected实现在某种程度上彼此不一致。
这里有关于ownDeletesAreVisible的JDBC规范:
" ...如果删除的行被删除或被空行替换,则DatabaseMetaData.ownDeletesAreVisible(int type)方法将返回true。如果ResultSet对象仍包含已删除的行,则返回false,这意味着删除对于给定类型的ResultSet对象的更改不可见... "
关于deletesAreDetected:
" ...方法deletesAreDetected返回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();
}
}
答案 0 :(得分:0)
这不是一个矛盾,JDBC 4.2 specification,第15.2.4.2节说(强调我的):
调用方法
deleteRow
后,将在基础数据源中删除当前行。 如果行被删除或被空行或无效行替换,则此删除在展开ResultSet
对象中可见。如果删除的行被删除或被空行替换,则该方法
DatabaseMetaData.ownDeletesAreVisible(int type)
将返回true
。的它 如果false
对象仍包含已删除的行,则返回ResultSet
,这意味着删除对于给定类型的ResultSet对象的更改不可见。[..]
如果
ResultSet
对象可以检测到删除,则ResultSet
方法rowDeleted
在删除当前行时返回true,否则返回false。 但是,如果ResultSet对象无法检测到删除,则rowDeleted
也会返回false
。可以调用方法DatabaseMetaData.deletesAreDetected(int type)
以查看指定类型的ResultSet
对象是否可以调用方法rowDeleted
来检测可见的删除。如果从deletesAreDetected
对象中删除了一行,则false
方法返回ResultSet
,如果删除的行被空行或无效行替换,则返回true。
需要在行之间进行一些阅读(并查看该部分中的示例代码),但这意味着deletesAreDetected
仅具有删除可见的意义,它会识别删除如何:该行已被删除(false
),或被替换为空行或无效行(true
)。
因此,当ownDeletesAreVisible
返回false
时,deletesAreDetected
的结果对于自己的&#39}没有任何意义。删除(除了'删除未被检测到');它可能对其他人有意义。删除,但我怀疑当你自己没有删除时,其他删除是可见的。
答案 1 :(得分:0)
我的结论:
dbmd.ownDeletesAreVisible(TYPE_SCROLL_INSENSITIVE)返回FALSE: " ...如果ResultSet对象仍包含已删除的行,则返回false ..."
dbmd.deletesAreDetected(TYPE_SCROLL_INSENSITIVE)返回FALSE: " ...如果从ResultSet对象中删除了一行,则返回false ..."
结果:
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.
dbmd.ownDeletesAreVisible(TYPE_SCROLL_INSENSITIVE)RETURNED TRUE:" ...如果删除的行被删除或被空行替换,该方法将返回true ..."
dbmd.deletesAreDetected(TYPE_SCROLL_INSENSITIVE)RETURNED TRUE:" ...如果删除的行被空行或无效行替换,该方法将返回true ..."
结果:
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规范。