杰瑞科技汇

Java插入MySQL为何中文乱码?

问题根源:字符集不一致

乱码的根本原因是 编码和解码使用了不同的“字符集”

Java插入MySQL为何中文乱码?-图1
(图片来源网络,侵删)

想象一下:

  • 你写了一封中文信(Java 里的字符串),用 UTF-8 编码成二进制流。
  • 你把这封信交给一个信使(JDBC 连接),但信使默认使用 GBK 字符集来解读这封信。
  • 信使解读后,发现一堆看不懂的乱码,然后把这个乱码信送到了目的地(MySQL 数据库)。
  • 数据库收到这封“乱码信”,如果它也使用 GBK 来存储,那么它就会忠实地把这堆乱码存起来,下次你读取时,Java 端用 UTF-8 解码,自然还是乱码。

解决方案就是:确保从 Java 代码到 MySQL 数据库,每一个环节都统一使用同一种字符集,强烈推荐使用 UTF-8


解决方案:全方位排查与设置

请按照以下步骤逐一检查和配置,确保每个环节都正确。

第 1 步:检查数据库和表的字符集

这是最根本的,如果你的数据库或表本身就不是 UTF-8,那么后续工作都白费。

Java插入MySQL为何中文乱码?-图2
(图片来源网络,侵删)
  1. 检查数据库字符集:

    SHOW VARIABLES LIKE 'character_set_database';

    理想结果应该是 utf8mb4,注意,这里不是 utf8utf8mb4 是 MySQL 中对 UTF-8 的完整实现,能支持包括 Emoji 在内的所有 Unicode 字符。

  2. 检查表的字符集:

    SHOW TABLE STATUS FROM `你的数据库名` LIKE '你的表名';

    查看 Collation 列,它应该以 utf8mb4_ 开头,utf8mb4_general_ciutf8mb4_unicode_ci

    Java插入MySQL为何中文乱码?-图3
    (图片来源网络,侵删)
  3. 检查列(字段)的字符集:

    SHOW CREATE TABLE `你的表名`;

    CREATE TABLE 语句中,查看存储中文的 VARCHARTEXT 字段定义,确保它也使用了 CHARACTER SET utf8mb4

如果发现不是 utf8mb4,请修改:

  • 修改数据库字符集:
    ALTER DATABASE `你的数据库名` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  • 修改表的字符集:
    ALTER TABLE `你的表名` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  • 修改列的字符集:
    ALTER TABLE `你的表名` MODIFY `列名` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

第 2 步:检查 JDBC 连接 URL (最关键的一步)

这是最容易出错的地方,在 JDBC URL 中,必须显式指定字符集为 UTF-8

错误示例 (可能导致乱码):

String url = "jdbc:mysql://localhost:3306/your_database";

正确示例 (必须添加 useUnicode=true&characterEncoding=UTF-8useUnicode=true&characterEncoding=utf8):

// 方式一:明确指定为 UTF-8 (推荐)
String url = "jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=UTF-8";
// 方式二:指定为 utf8 (效果相同)
String url = "jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=utf8";

注意:

  • useUnicode=true:这个参数是必须的,它告诉 JDBC 驱动使用 Unicode 字符集。
  • characterEncoding=UTF-8:指定连接的字符编码。
  • 最佳实践:如果你的 MySQL 版本是 5.5.3 或更高版本,强烈推荐使用 utf8mb4 字符集,这需要你的数据库、表、列都已经设置为 utf8mb4,URL 中也使用 utf8mb4
    String url = "jdbc:mysql://localhost:3306/your_database?useUnicode=true&characterEncoding=utf8mb4";

第 3 步:检查 MySQL 服务器的全局字符集

即使你的数据库和表是 UTF-8,MySQL 服务器的默认字符集是别的,也可能影响新创建的数据库或表。

-- 查看所有字符集相关的变量
SHOW VARIABLES LIKE 'character_set_%';

重点关注以下几个变量:

  • character_set_server:服务器的默认字符集。
  • character_set_database:当前数据库的字符集。
  • character_set_connection:连接的字符集。
  • character_set_results:结果集的字符集。

建议配置 (在 my.cnfmy.ini 中):

[mysqld]
# 设置服务器默认字符集为 utf8mb4
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
# 设置客户端连接默认字符集
init-connect='SET NAMES utf8mb4'
[client]
# 设置客户端连接默认字符集
default-character-set = utf8mb4

修改完配置文件后,需要重启 MySQL 服务。

第 4 步:检查 Java 代码和项目环境

  1. Java 源文件编码:

    • 确保你的 Java 源文件(.java 文件)本身是以 UTF-8 编码保存的。
    • 在主流 IDE(如 IntelliJ IDEA, Eclipse)中,检查并设置项目文件的编码为 UTF-8,在 IDEA 中,File -> Settings -> Editor -> File Encodings,将 Global EncodingProject Encoding 都设置为 UTF-8
  2. 确保 Java 环境正确:

    现代 Java 版本(JDK 8+)的默认字符集通常是 UTF-8,但最好确保你的应用服务器或运行环境没有因为配置问题而改变默认字符集。


一个完整的、正确的示例

假设你已经完成了上述所有设置,下面是一个没有乱码的 Java 插入代码示例。

MySQL 表结构 (user_info):

CREATE DATABASE `test_db` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE `test_db`;
CREATE TABLE `user_info` (
  `id` INT AUTO_INCREMENT PRIMARY KEY,
  `name` VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
  `city` VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
);

Java 代码 (InsertData.java):

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class InsertData {
    // 数据库连接信息
    private static final String DB_URL = "jdbc:mysql://localhost:3306/test_db?useUnicode=true&characterEncoding=utf8mb4";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "your_password";
    public static void main(String[] args) {
        // 要插入的中文数据
        String name = "张三";
        String city = "北京";
        // 使用 try-with-resources 语句,确保连接和语句自动关闭
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            // 准备 SQL 语句,使用 ? 作为占位符,防止 SQL 注入
            String sql = "INSERT INTO user_info (name, city) VALUES (?, ?)";
            try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
                // 设置参数,索引从 1 开始
                pstmt.setString(1, name);
                pstmt.setString(2, city);
                // 执行插入
                int affectedRows = pstmt.executeUpdate();
                if (affectedRows > 0) {
                    System.out.println("数据插入成功!插入的姓名: " + name);
                } else {
                    System.out.println("数据插入失败。");
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

排查清单

如果遇到乱码,请按以下清单逐一核对:

检查项 推荐设置 检查/修改命令
数据库字符集 utf8mb4 SHOW VARIABLES LIKE 'character_set_database';
ALTER DATABASE ... CHARACTER SET utf8mb4;
表字符集 utf8mb4 SHOW TABLE STATUS ...;
ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4;
列字符集 utf8mb4 SHOW CREATE TABLE ...;
ALTER TABLE ... MODIFY ... CHARACTER SET utf8mb4;
JDBC URL ?useUnicode=true&characterEncoding=utf8mb4 检查 Java 代码中的连接字符串
MySQL 服务配置 character-set-server = utf8mb4 检查 my.cnf/my.ini 文件并重启 MySQL
Java 源文件编码 UTF-8 在 IDE 中检查项目文件编码

只要以上所有环节都统一使用 utf8mb4,Java 插入 MySQL 的中文乱码问题就可以从根本上解决。

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