MySQL数据库数据正确却返回空ResultSet的排查求助
我仔细梳理了你遇到的问题:同一个数据库连接能正常加载ActionBlock数据,但加载关联的PermanentLocation时却返回空ResultSet,而且直接在DBMS执行相同逻辑的SQL能拿到结果。结合你提供的代码和排查记录,我整理了几个最可能的问题点和修复方案:
1. 优先排查:ServerID的取值不一致(最可能的根源)
我注意到两段代码中获取ServerID的方式不一样:
- 在
loadBlocksFromDatabase里,你用的是KaranteeniCore.getServerIdentificator() - 在
loadLocation里,你用的是KaranteeniPlugin.getServerIdentificator()
这两个方法大概率返回了不同的服务器标识字符串!如果location表中存储的serverID和loadLocation传入的不匹配,自然查不到任何数据。
修复步骤:
把loadLocation里的ServerID获取逻辑改成和ActionBlock一致,比如:
// 修改PermanentLocation.loadLocation中的这一行 st.setString(2, KaranteeniCore.getServerIdentificator());
2. 修正PermanentLocation中的世界判断逻辑
虽然这不是ResultSet为空的直接原因,但这段代码逻辑明显写反了,会导致后续出现错误:
if(world == null) return null; else Bukkit.getLogger().log(Level.SEVERE, "Could not find world " + w);
正确的逻辑应该是当世界不存在时打印日志并返回null,否则继续创建Location:
if(world == null) { Bukkit.getLogger().log(Level.SEVERE, "Could not find world " + w); return null; } // 继续执行Location创建逻辑...
3. 验证UUID字符串的大小写匹配
部分数据库(比如PostgreSQL)对字符串大小写敏感,Java中UUID.toString()生成的字符串包含大写字母(比如-分隔后的段),如果location表的id字段存储的是小写UUID,就会导致匹配失败。
验证与修复:
在loadLocation中添加日志,打印实际传入的UUID和ServerID:
Bukkit.getLogger().info("Querying location: UUID=" + uuid.toString() + ", ServerID=" + KaranteeniPlugin.getServerIdentificator());
对比数据库中location表的对应字段,如果大小写不一致,可以统一转为小写后查询:
st.setString(1, uuid.toString().toLowerCase());
4. 再次确认PreparedStatement的参数绑定顺序
虽然你的代码看起来参数顺序是对的(先id,再serverID),但还是建议再核对一次:
SQL语句是 SELECT ... FROM location WHERE id = ? AND serverID = ?;
参数绑定顺序是先id(st.setString(1, uuid.toString())),再serverID(st.setString(2, ...)),确保没有搞反。
5. 排查事务状态影响
如果当前连接处于未提交的事务中,可能导致查询看不到最新数据。可以尝试在查询Location前添加自动提交设置:
conn.setAutoCommit(true);
或者如果之前有手动事务,先提交再执行Location查询。
内容的提问来源于stack exchange,提问作者Nuubles

