【问题标题】:Encoding hell with Spring, Hibernate and MySQL使用 Spring、Hibernate 和 MySQL 编码地狱
【发布时间】:2019-06-03 11:02:08
【问题描述】:

我遇到了一个让我发疯的编码问题。我的网站支持英语和西班牙语两种语言。我的一些表(由hibernate生成)有作为排序规则utf8_general_ci,还有一些,我不知道为什么,有latin1_swedish_ci。但令我震惊的是,当人们使用我的联系人表单并在其中输入例如一个带有“ñ”的单词时,我的 Spring 控制器会接收它并向我发送一封电子邮件,这是好的(我的意思是它有 ñ),然后保存MySQL 上的数据。但是,当我检查保存在 MySQL 中的内容(并且我的 Contacts 表有一个 utf8_general_ci 排序规则)时,里面出现了一些可怕的符号来代替“ñ”字符,比如 Ãlvaro Núñez Cabeza de Váca。恢复,jsp页面声明了UTF-8,表是utf8_general_ci,hbn也声明了utf-8:

# hibernate props
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show.sql=true
hibernate.hbm2ddl.auto=update
hibernate.format_sql=true
# hibernate props added to fix 4bytes encoded characters
hibernate.connection.CharSet=utf8mb4
hibernate.connection.characterEncoding=utf8
hibernate.connection.useUnicode=true

但所有这些都没有按预期工作。

我们将非常欢迎任何帮助。

解决方案:至少对我来说,唯一可行的解​​决方法是在我的 web.xml 中添加一个过滤器。我很确定有更好的方法以更优雅的方式解决编码问题,但在我的情况下,所有内容都配置为使用 UTF-8 并且我的表单的一部分运行良好,但其他人将 Álvar Núñez Cabeza de Vaca 显示为 Ãlvar Núñez卡贝萨德瓦卡。 过滤器是:

<filter>  
    <filter-name>encodingFilter</filter-name>  
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>  
    <init-param>  
       <param-name>encoding</param-name>  
       <param-value>UTF-8</param-value>  
    </init-param>  
    <init-param>  
       <param-name>forceEncoding</param-name>  
       <param-value>true</param-value>  
    </init-param>  
</filter>  
<filter-mapping>  
    <filter-name>encodingFilter</filter-name>  
    <url-pattern>/*</url-pattern>  
</filter-mapping> 

正如这篇文章中的那样Spring MVC UTF-8 Encoding

【问题讨论】:

    标签: mysql hibernate utf-8 character-encoding


    【解决方案1】:

    听起来可能存在多个问题。因此,计划进行多项修复。

    • 始终使用UTF-8。 (Latin1 适用于英语 + 西班牙语,但该行业正在逐渐远离此。)
    • 旧版本的 MySQL 默认使用 latin1 字符集(和 latin1_swedish_ci 排序规则)。
    • 对 MySQL 使用 CHARACTER SET utf8mb4(不是 utf8)。相当于外界的UTF-8。在该配置的 sn-p 中,将 characterEncoding=utf8 更改为 characterEncoding=UTF-8
    • 您提到了utf8_general_ci -- 更改为utf8mb4... 并考虑utf8mb4_unicode_520_ci(总体最佳)或utf8mb4_spanish_ciutf8mb4_spanish2_ci
    • NúñezNúñez 的 Mojibake。当系统的一部分正在使用 latin1 而另一部分正在使用 UTF-8 时,就会发生这种情况。
    • 如果您需要恢复混乱的数据(由于 Mojibake),我们可以讨论。最好从头开始,始终使用UTF-8/utf8mb4。

    有关诊断 Mojibake 等的更多信息:Trouble with UTF-8 characters; what I see is not what I stored

    对于排序规则差异:http://mysql.rjweb.org/utf8_collations.html -- 主要与 chllñ 相关 -- 您是否希望将它们视为“单独的字母”? (应该chcgci 之间排序,还是在cz 之后排序?等等)

    对于 Java/JDBC/Hibernate/等:?useUnicode=true&amp;characterEncoding=UTF-8

    【讨论】:

    • 嗨 Rick,非常感谢,我正在尝试您的建议并将有问题的表移动到 utf8mb4 但仍然失败,奇怪的是我在同一个数据库中观察到我有另一个表 USER 用 latin1 和整理latin1_swedish_ci 适用于西班牙语字符。然后我尝试将我的另一个表从 utf8 移动到 latin1 但它仍然失败,然后我移动到 utf8mb4_spanish_ci; ALTER TABLE Con​​tacts CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_spanish_ci;所以,现在我完全迷路了。
    • @lm2a - 不仅仅是桌子;它也是SET NAMES 或连接参数。 它们告诉mysql在client中使用什么编码。这通常是错误出现的地方。
    • 感谢 Rick,但两张表都使用相同的连接器。这里有参数:jdbc:mysql://my_dabase_ip:3306/mydatabasename?useUnicode=true&character_set_server=utf8mb4&createDatabaseIfNotExist=true&autoReconnect=true&connectTimeout=60000&socketTimeout=60000。我使用的是 MySQL 5.7,但它是 Google Cloud 上的 Maria 实例。并且我加了一个标记:character_set_server = utf8mb4 关于SET NAMES,也许这是Hibernate做的,但我从来没有做过。但是,如何在相同的情况下,一个有效而另一个无效呢?
    • 也许这很重要,我发现正确保存的对象是用使用 HibernateTemplate 的 DAO 保存的,而不能正常工作的对象是使用 SessionFactory 保存的(也来自 Hibernate)。 AFAIK SessionFactory 是推荐的 Spring 选项,但这里似乎 HibernateTemplate 做得更好。
    • 此外,这似乎不是 MySQL 的问题,因为我可以使用 MySQLWorkbench 输入像 Álvar Núñez Cabeza de Vaca 这样的名称,并且可以正常保存。所以,问题可能出在我的 Hibernate 配置的方式上。
    猜你喜欢
    • 2016-03-31
    • 2017-01-24
    • 1970-01-01
    • 2015-12-05
    • 2011-08-08
    • 2013-03-06
    • 2013-07-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多