MySQL存储Unicode及特殊字符问题:escapeJava转义后存储异常致解码失败
解决MySQL存储Unicode转义字符丢失反斜杠的问题
嘿,这个坑我之前踩过!你遇到的问题本质是MySQL默认会把反斜杠\当作SQL转义字符,导致你用StringEscapeUtils.escapeJava()生成的\uxxxx格式字符串存进数据库后,反斜杠被吃掉,只剩下uxxxx,自然unescapeJava()解码失败。
问题根源
MySQL默认的sql_mode中没有启用NO_BACKSLASH_ESCAPES,这意味着它会解析字符串中的反斜杠,把它当作转义标记。比如你存入\u0022(双引号的Unicode转义),MySQL会认为你想转义后面的u,但u不是特殊转义字符,所以直接丢弃反斜杠,最终存储的内容变成u0022。
解决方案
方案1:修改MySQL连接参数(推荐)
在你的JDBC URL中添加sessionVariables=sql_mode='NO_BACKSLASH_ESCAPES',让MySQL不再处理反斜杠作为转义字符。示例URL:
jdbc:mysql://localhost:3306/your_db?useSSL=false&characterEncoding=UTF-8&sessionVariables=sql_mode='NO_BACKSLASH_ESCAPES'
这样设置后,你直接用StringEscapeUtils.escapeJava()转义后的字符串存入数据库,反斜杠会被完整保留,读取后用unescapeJava()就能正常解码。
方案2:手动双重转义反斜杠
如果无法修改连接参数,可以在转义后把反斜杠再转义一次,让MySQL存完后保留单个反斜杠:
String rawContent = "包含\"双引号和Unicode的内容"; // 先转义特殊字符为\uxxxx格式 String escaped = StringEscapeUtils.escapeJava(rawContent); // 把每个\替换成\\,这样MySQL会把\\解析成单个\ String doubleEscaped = escaped.replace("\\", "\\\\"); // 存入数据库的是\\uxxxx,读取后变成\uxxxx,可正常解码
方案3:全局设置MySQL的sql_mode
如果你有权限修改MySQL配置,可以在my.cnf(或my.ini)中添加:
sql_mode = NO_BACKSLASH_ESCAPES
重启MySQL后,所有连接都会生效,不需要修改代码或连接参数。
注意事项
- 如果你使用
NO_BACKSLASH_ESCAPES,SQL中的单引号需要用两个单引号''来转义,而不是\',不过如果用PreparedStatement做参数化查询,这个问题会被自动处理,不用担心SQL注入。 - 优先推荐方案1,因为它不需要修改业务代码,配置一次即可生效,避免手动转义带来的潜在错误。
内容的提问来源于stack exchange,提问作者Prashant Pandey
相关产品推荐
相关产品推荐

