杰瑞科技汇

java mysql 插入中文乱码

问题根源:字符集不统一

想象一下你的中文数据 "你好" 在整个旅程中是如何变化的:

java mysql 插入中文乱码-图1
(图片来源网络,侵删)
  1. Java 代码层String str = "你好"; 在 Java 内存中,它使用的是 UTF-16 编码。
  2. JDBC 驱动层:JDBC 驱动需要将 Java 字符串转换成某种格式(通常是字节流)才能发送给 MySQL,如果配置不当,这里可能会使用错误的编码(如 Latin1)进行转换。
  3. 网络传输层:字节流通过网络从你的应用服务器发送到 MySQL 服务器,这个过程本身不改变数据,但两端的字符集配置必须兼容。
  4. MySQL 服务器层:MySQL 接收到字节流后,需要知道这些字节是用什么编码表示的,才能正确地“解读”成字符,如果服务器配置的默认字符集是 latin1,它会错误地用 latin1 去解读 UTF-8 的字节流,导致乱码。
  5. MySQL 数据库/表/字段层:即使服务器默认是 utf8,你创建数据库、表或定义字段时,如果指定了其他的字符集(如 latin1),那么数据最终还是会以错误的字符集存储。

只要上述任何一个环节的字符集不是 UTF-8,就极有可能产生乱码。


完整解决方案(必做项)

请按照以下步骤逐一检查和修改,确保整个链路都统一使用 UTF-8,这是最可靠的方法。

第 1 步:确保 MySQL 服务端和数据库是 UTF-8

这是最根本的一步,如果数据库本身就不是 UTF-8,Java 做再多努力也无济于事。

  1. 检查 MySQL 服务器的默认字符集 登录到 MySQL 命令行,执行以下命令:

    java mysql 插入中文乱码-图2
    (图片来源网络,侵删)
    SHOW VARIABLES LIKE 'character_set_server';

    确保返回值是 utf8mb4(重要:推荐使用 utf8mb4 而不是 utf8,因为 utf8mb4 完全兼容 utf8 并且支持 Emoji 表情和一些特殊字符)

  2. 检查和创建数据库 创建数据库时,必须指定字符集和排序规则。

    -- 推荐:创建数据库时指定字符集
    CREATE DATABASE my_database CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

    如果数据库已存在,可以修改它的字符集:

    ALTER DATABASE my_database CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  3. 检查和创建表/字段 创建表和定义 VARCHAR, TEXT 等字段时,也要指定字符集。

    java mysql 插入中文乱码-图3
    (图片来源网络,侵删)
    USE my_database;
    -- 推荐:在表级别定义字符集,会应用到所有字段
    CREATE TABLE my_table (
        id INT PRIMARY KEY AUTO_INCREMENT,
        name VARCHAR(100) -- 这里会继承数据库的字符集
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    -- 或者更明确地在字段级别定义
    CREATE TABLE my_table (
        id INT PRIMARY KEY AUTO_INCREMENT,
        name VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

    如果表已存在,可以修改表的字符集(这会修改现有字段的字符集,但不会修复已存的乱码数据):

    ALTER TABLE my_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

第 2 步:配置 JDBC 连接字符串(URL)

这是 Java 连接 MySQL 的关键配置,在 JDBC URL 中显式地指定字符集为 UTF-8

错误的 URL: jdbc:mysql://localhost:3306/my_database

正确的 URL: jdbc:mysql://localhost:3306/my_database?useUnicode=true&characterEncoding=UTF-8

最佳实践 URL (推荐使用 utf8mb4): jdbc:mysql://localhost:3306/my_database?useUnicode=true&characterEncoding=utf8mb4

参数解释:

  • useUnicode=true: 启用 Unicode 字符集支持。
  • characterEncoding=UTF-8 (或 utf8mb4): 指定客户端和服务器通信时使用的字符编码,这会告诉 JDBC 驱动如何将 Java 字符串编码成字节流发送给 MySQL。

第 3 步:检查 Java 代码和 IDE 环境

  1. 确保源代码文件编码是 UTF-8

    • 在 IDE (如 IntelliJ IDEA/Eclipse) 中:检查项目/文件的编码设置,通常在右下角或文件属性中可以看到,确保它被设置为 UTF-8,如果源文件本身是 GBK 等编码,编译后也可能出现问题。
  2. 检查编译后的 .class 文件编码

    • 在编译 Java 文件时,可以通过 -encoding 参数指定源文件编码,确保编译过程不出错。
    • javac -encoding UTF-8 MyJavaFile.java
  3. 确保服务器环境(如 Tomcat)的编码

    • 如果你使用的是 Web 服务器(如 Tomcat),请确保其处理请求和响应的编码也是 UTF-8,通常在 web.xml 中配置 <filter> 来设置请求编码:
      <filter>
      <filter-name>CharacterEncodingFilter</filter-name>
      <filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</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>CharacterEncodingFilter</filter-name>
      <url-pattern>/*</url-pattern>
      </filter-mapping>

检查清单和调试方法

如果按照以上步骤操作后仍有问题,请对照以下清单检查:

检查点 命令/配置 预期结果
MySQL 服务端字符集 SHOW VARIABLES LIKE 'character_set_server'; utf8mb4
MySQL 数据库字符集 SHOW CREATE DATABASE my_database; utf8mb4
MySQL 表字符集 SHOW CREATE TABLE my_table; utf8mb4
JDBC URL jdbc:mysql://...?useUnicode=true&characterEncoding=utf8mb4 包含该参数
Java 源文件编码 IDE 设置 UTF-8
数据库中已存数据 SELECT name FROM my_table WHERE id = 1; 显示为乱码(说明是旧数据)

如何修复已存的乱码数据?

如果数据库中已经存在乱码数据,说明这些数据在被错误地编码后存储了,修复它们的唯一方法是从正确的来源重新获取数据并插入

不要尝试直接在数据库里用 CONVERT()CAST() 修复,因为原始字节信息已经丢失,你无法知道它最初是什么编码。

如果你的数据是按 GBK 编码被错误地存成了 latin1 格式,你可以这样尝试修复(不保证100%成功,仅作示例):

-- 这种方法风险很高,仅当你确定原始编码时才可尝试
UPDATE my_table SET name = CONVERT(CAST(name AS BINARY) USING gbk) WHERE id = 1;

强烈建议: 最安全的方法是删除乱码数据,然后让你的应用程序(已修复好编码问题)重新生成并插入正确的数据。


完整示例代码

下面是一个完整的 Java 插入示例,包含了正确的 JDBC URL。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class MysqlInsertExample {
    // 数据库连接信息
    // !!! 关键点:在 URL 中添加 useUnicode=true&characterEncoding=utf8mb4
    private static final String DB_URL = "jdbc:mysql://localhost:3306/my_database?useUnicode=true&characterEncoding=utf8mb4";
    private static final String USER = "root";
    private static final String PASS = "your_password";
    public static void main(String[] args) {
        // 要插入的中文数据
        String chineseName = "张三";
        String chineseDescription = "这是一个测试,包含中文和 Emoji 😊";
        // 使用 try-with-resources 确保 Connection 和 PreparedStatement 被自动关闭
        try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
             PreparedStatement pstmt = conn.prepareStatement("INSERT INTO my_table (name, description) VALUES (?, ?)")) {
            // 设置参数
            pstmt.setString(1, chineseName);
            pstmt.setString(2, chineseDescription);
            // 执行插入
            int affectedRows = pstmt.executeUpdate();
            if (affectedRows > 0) {
                System.out.println("数据插入成功!");
            } else {
                System.out.println("数据插入失败。");
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

解决 Java MySQL 中文乱码问题的核心思想是“统一”

  1. 统一数据库环境:服务器、数据库、表、字段全部使用 utf8mb4
  2. 统一连接配置:JDBC URL 中明确指定 characterEncoding=utf8mb4
  3. 统一开发环境:确保 Java 源代码和项目文件是 UTF-8 编码。

只要这三个环节都正确配置,99% 的中文乱码问题都能迎刃而解。

分享:
扫描分享到社交APP
上一篇
下一篇