SQLite PreparedStatement始终返回空ResultSet问题排查
你的问题在SQLite旧版本JDBC驱动里其实挺常见的,咱们一步步来排查和解决:
1. 先去掉查询语句末尾的分号
SQLite 3.21.0.1这类旧版本的JDBC驱动,对PreparedStatement语句末尾的分号处理存在bug。你看你的预编译查询语句最后带了分号:
String query = "SELECT * FROM users WHERE email= ?;";
虽然静态SQL(createStatement用的)带分号没问题,但驱动对预编译SQL的解析逻辑不一样。先试试把分号去掉:
String query = "SELECT * FROM users WHERE email= ?";
2. 核对PreparedStatement的参数绑定是否正确
你已经打印了preparedStatement.toString(),仔细看这个日志输出,确认参数是否正确绑定到SQL里。比如日志应该显示类似SELECT * FROM users WHERE email= 'test@example.com'的内容,如果参数没显示或者显示异常,那大概率是驱动的参数绑定出了问题。
3. 检查连接的一致性
两个方法都调用了getConnection(),要确认这个方法每次返回的连接是否一致,以及连接状态是否相同(比如是否处于事务中、是否开启只读模式等)。比如如果getConnection()返回连接池里的不同连接,其中某个连接有未提交的事务,可能导致查询结果不一致。
可以在方法里加一行日志确认连接对象:
Connection conn = getConnection(); log.info("当前连接哈希值: " + conn.hashCode());
4. 升级SQLite JDBC驱动版本
3.21.0.1是2017年的旧版本,存在不少预编译语句相关的已知bug。建议升级到较新的稳定版本(比如3.40.0.0以上),这类参数绑定的问题在新版本里基本都被修复了。
5. 手动确认数据库中存在目标数据
用SQLite命令行或者可视化工具(比如DB Browser for SQLite)执行查询语句,确认数据库里确实有对应email的记录。比如执行:
SELECT * FROM users WHERE email='你的测试邮箱@example.com';
先排除数据本身不存在的可能性。
修改后的示例代码
顺便给你优化下代码,用try-with-resources确保资源能正确关闭,避免泄漏:
public boolean checkIfUsersExists(String email) throws SQLException { String query = "SELECT * FROM users WHERE email= ?"; try (Connection conn = getConnection(); PreparedStatement preparedStatement = conn.prepareStatement(query)) { preparedStatement.setString(1, email); log.info(preparedStatement.toString()); try (ResultSet resultSet = preparedStatement.executeQuery()) { return resultSet.next(); } } }
内容的提问来源于stack exchange,提问作者masterofdisaster

