JDBC执行SQL丢失部分内容,SQL编辑器运行正常的问题排查
问题:Java使用mysql-connector-java-5.1.7连接MariaDB执行拼接JSON的SQL时丢失字段值
问题重现
执行的SQL语句
SELECT CONCAT( '{ ', '"test": ', '{', '"a": true,', /* don't set to false */ '"b": { "t": true },', '"c": 2', '},', '"b": { "t": true } ', '}' ) AS test
SQL编辑器执行结果
{ "test": {"a": true,"b": { "t": true },"c": 2},"b": { "t": true } }
Java代码执行结果
{ "test": {"a": true,"b": ,"c": 2},"b": { "t": true } }
对应的Java代码
import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class testSQL { private static final String DB_URL = ""jdbc:mysql://localhost:3306/database?characterEncoding=utf-8""; private static final String DB_USER = ""your_username""; private static final String DB_PASSWORD = ""your_password""; public static void main(String[] args) { String sql = ""SELECT\n\tCONCAT(\n\t'{ ',\n\t\t'\\"test\\": ',\n\t\t'{',\n\t\t\t'\\"a\\": true,',\t/* don't set to false */\n\t\t\t'\\"b\\": { \\"t\\": true },',\n\t\t\t'\\"c\\": 2',\n\t\t'},',\n\t\t'\\"b\\": { \\"t\\": true } ',\n\t'}'\n\t) AS test"; try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD); PreparedStatement stmt = conn.prepareStatement(sql); ResultSet rs = stmt.executeQuery()) { while (rs.next()) { System.out.println(rs.getObject(1)); } } catch (SQLException e) { e.printStackTrace(); } } }
问题原因
这是mysql-connector-java 5.1.7版本的已知bug:旧版本JDBC驱动会错误地将结果字符串中的{ "t": true }识别为预编译参数占位符的格式(类似{?}的结构),进而对该部分内容进行了错误的清空处理,最终导致第一个b字段的值丢失。
解决方法
- 升级JDBC驱动版本:将mysql-connector-java升级到5.1.8及以上版本(推荐使用5.1.x系列的稳定新版本,或直接切换为MariaDB官方的
mariadb-java-client驱动),新版本已修复该字符串解析bug。 - 临时规避方案:若暂时无法升级驱动,可在SQL中对大括号进行转义,将
{替换为\\{,}替换为\\},避免驱动误识别。修改后的对应SQL片段示例:
'"b": \\{ "t": true \\},'
内容的提问来源于stack exchange,提问作者Curtis
相关产品推荐
相关产品推荐

