我的应用程序在一个平台上使用MySQL,而在另一个平台上使用SQLite,因此存在差异,例如在使用DELETE FROM USERS
:
- 在MySQL上,
PreparedStatement.getResultSet()
返回null
。 - 在SQLite上,
PreparedStatement.getResultSet()
抛出java.sql.SQLException: no ResultSet available
这可能是也可能不是SQLite实现中的错误(我认为它应该返回null
),但我必须以某种方式处理这个问题。
我可以使用try { ... } catch (SQLException e) { ... }
,如果异常消息是"no ResultSet available"
,只需手动返回null。但这感觉不像是一个正确的方法。
我可以设置一个if来检查正在使用的JDBC驱动程序并做出相应的反应,但是,这又不是一个解决问题的好方法。
我真正想要的是像.hasResultSet()
这样的方法,返回boolean
或一种从已执行的语句中获取SQL命令(SELECT, UPDATE, INSERT
等)的方法。
当执行返回未知数量结果的查询时,则需要使用execute()
。这个方法返回一个boolean
,指示结果的类型:
-
true
: result is aResultSet
-
false
: result is an update count
如果结果是true
,则使用getResultSet()
检索ResultSet
,否则使用getUpdateCount()
检索更新计数。如果更新计数为-1
,则意味着没有更多的结果。请注意,当当前结果是ResultSet
时,更新计数也将是-1
。如果没有更多的结果或者结果是更新计数,那么知道getResultSet()
应该返回null也是很好的,因此SQL Lite抛出异常的行为似乎是错误的。
现在,如果您想检索更多的结果,您调用getMoreResults()
(或它的兄弟接受int
参数)。此方法的boolean
返回值与execute()
的含义相同,所以false
并不表示没有结果!
如果getMoreResults()
返回false 并且 getUpdateCount()
返回-1
(也在Javadoc中记录)
本质上,这意味着如果你想正确处理所有结果,你需要做这样的事情:
PreparedStatement pstmt = connection.prepareStatement(...);
// ...
boolean result = pstmt.execute();
while(true) {
if (result) {
ResultSet rs = pstmt.getResultSet();
// Do something with resultset ...
} else {
int updateCount = pstmt.getUpdateCount();
if (updateCount == -1) {
// no more results
break;
}
// Do something with update count ...
}
result = pstmt.getMoreResults();
}
问题是使用了无效的方法来执行删除操作。而不是使用getResultSet
你应该使用Statement#execute(String)
IMHO异常在SQLite实现中比null在MySQL中更有效。因为delete
不返回集合,而是一个删除行的标量值。