UTF8mb4 unicode 破坏 MariaDB JDBC 驱动程序
Posted
技术标签:
【中文标题】UTF8mb4 unicode 破坏 MariaDB JDBC 驱动程序【英文标题】:UTF8mb4 unicode breaking MariaDB JDBC driver 【发布时间】:2020-11-23 17:53:23 【问题描述】:我有一些包含 unicode 字符的产品名称
⚠️????请阅读!可工作的柯达 DC215 变焦 1.0MP 数码相机 - 英国 卖家
heidiSQL 中的查询显示它很好
我今天早上从 mysql 迁移过来设置了新的 MariaDB,但是当使用 MariaDB JDBC 通过 ColdFusion 查询检索记录时,我得到了
java.lang.StringIndexOutOfBoundsException: begin 0, end 80, length 74
at java.base/java.lang.String.checkBoundsBeginEnd(String.java:3410)
at java.base/java.lang.String.substring(String.java:1883)
at org.mariadb.jdbc.internal.com.read.resultset.rowprotocol.TextRowProtocol.getInternalString(TextRowProtocol.java:238)
at org.mariadb.jdbc.internal.com.read.resultset.SelectResultSet.getString(SelectResultSet.java:948)
productname 字段排序规则是utf8mb4_unicode_520_ci
,我尝试了几个选项。我已经尝试在表和数据库级别进行设置。
ColdFusion 管理中的 JDBC 连接字符串是jdbc:mysql://localhost:3307/usedlens?useUnicode=true&characterEncoding=UTF-8
我注意到从一开始就使用 MariaDB 的实时生产数据库我没有这个问题,但默认字符集是 latin1,并且与数据库相同的记录是
????请阅读!可使用的柯达 DC215 变焦 1.0MP 数码相机 - 英国卖家
【问题讨论】:
见***.com/questions/38363566/…中的“问号” 是否正好有 4 个问号?我希望这 2 个表情符号有 10 个:十六进制:E29AA0 EFB88F F09F93B7
@RickJames 我照原样复制了文本,所以是的 4 ????,它与在 prod 上作为 dev 导入的产品相同。顺便说一句,如果我在我的数据库处理它们之前没有说清楚,请参阅添加的屏幕截图,这只是 Coldfusion 使用的 jdbc 引发了错误。
我没用过MariaDB,但你不应该指定characterEncoding=utf8mb4
吗?
仅供参考:我将 CF2016 与 Microsoft JDBC SQL 驱动程序一起使用,并且 NVARCHAR 字段和表情符号已正确存储(使用默认拉丁排序规则)。我们还在同一列中支持多种外语,并且没有任何查询问题。我想知道这是否是一个严格的 JDBC 问题。
【参考方案1】:
以下是我们如何去除高位 ASCII 字符,同时保留任何可能被挽救的字符:
string function ASCIINormalize(string inputString="")
return createObject( 'java', 'java.text.Normalizer' ).normalize( javacast("string", arguments.inputString) , createObject( 'java', 'java.text.Normalizer$Form' ).valueOf('NFD') ).replaceAll('\pInCombiningDiacriticalMarks+','').replaceAll('[^\pASCII]+','');
productname = ASCIINormalize(productname);
/*
Comparisons using java UDF versus reReplace regex:
"ABC Café ’test" (note: High ASCII non-normal whitespace characters used.)
ASCIINormalize = "ABC Cafe test"
reReplace = "ABC Caf test"
"čeština"
ASCIINormalize = "cestina"
reReplace = "etina"
"Häuser Bäume Höfe Gärten"
ASCIINormalize = "Hauser Baume Hofe Garten"
reReplace = "Huser Bume Hfe Grten"
*/
【讨论】:
注意:以上解决方案来自***.com/a/11642205/693068,我还建议使用名为 JUnidecode 的第三方 java 库。【参考方案2】:这是由于构成表情符号的一系列高位 ASCII 字符造成的。在将 MSSQL 数据导出到 UTF-8 文件以使用 3rd 方工具转换为 Excel 时,我遇到了类似的问题。在这种情况下,数据库和文件是正确的,但第 3 方工具遇到表情符号时会崩溃。
我们解决此问题的方法是将表情符号转换为其别名,这样信息就不会在此过程中丢失。 (如果你去掉高位 ASCII 字符,你可能会丢失一些上下文。)为了清理表情符号以使用别名,我写了这个 ColdFusion cf-emoji-java (CFC) 以利用 emoji-java (JAR 文件) 将表情符号转换为它们的 ASCII7 安全别名.
emojijava = new emojijava();
emojijava.parseToAliases('I like ?'); // I like :pizza:
【讨论】:
删除表情符号可能是我唯一的选择,谢谢。但是正如您在添加的屏幕截图中看到的那样,数据库确实可以很好地处理它们,只是 ColdFusion 中的 JDBC 驱动程序引发了错误,我原以为它已经通过某处的正确配置解决了。 表情符号对于产品领域没有意义。如果您期望的文本应该是 ASCII7,您可以完全去除它们。如果这些是用户 cmets,则可能会丢失某些上下文或表达式,具体取决于表情符号的使用方式。【参考方案3】:因为……
我并不是真正从事支持表情符号的业务 我的数据只是在可预见的未来针对英国、欧洲和美国的产品名称 我不想在生产中遇到同样的麻烦(已经默认为 latin1_swedish_ci)我决定……
匹配生产,所以我在
的帮助下将数据库、表和字段设置为 latin1_swedish_ciHow to change the CHARACTER SET (and COLLATION) throughout a database?
并去除产品名称中的非 ASCII 字符
== 编辑不要这样做,它会删除太多有用的字符==
<cfset productname = reReplace(productname, "[^\x20-\x7E]", "", "ALL")>
【讨论】:
以上是关于UTF8mb4 unicode 破坏 MariaDB JDBC 驱动程序的主要内容,如果未能解决你的问题,请参考以下文章
MySQL 数据库 - 将字符集和排序规则转换为 utf8mb4 和 utf8mb4_unicode_ci?
MySQL数据库 - 将characterset和collat ion转换为utf8mb4和utf8mb4_unicode_ci?