Caused by: java.sql.SQLException: Incorrect string value: ‘\xF0\x9F\x98\x80\xE3\x80...‘ for column

本文详细介绍了在Java应用中遇到的SQL异常,因特殊字符无法正确存储到MySQL数据库引发的问题,提供了包括修改数据库、表字段和连接字符集,以及升级驱动包和转换字符编码在内的解决方案。
摘要由CSDN通过智能技术生成

目录

Caused by: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x80\xE3\x80...' for column 'return_value' at row 1

解决方案

1. 修改数据库字符集

2. 修改表字段字符集

3. 修改表字符集

4. 修改连接字符集

5.升级mysql驱动包

6.转换字符编码

java示例

结论


Caused by: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x80\xE3\x80...' for column 'return_value' at row 1

在开发过程中,我们有时会遇到数据库存储数据时出现字符编码问题的情况。其中一个常见的错误是​​Caused by: java.sql.SQLException: Incorrect string value​​,并且提到了具体的列名和行号。本文将详细介绍这个错误的原因和解决方案。

错误原因分析

这个错误通常出现在使用MySQL数据库时,当我们向某个列中插入一些特殊字符或表情符号时触发。错误信息中的​​'\xF0\x9F\x98\x80\xE3\x80...'​​是Unicode编码表示,它表示了一个表情符号。这表明MySQL数据库当前的字符集无法正确处理这个字符,导致存储失败。 该错误通常出现在以下情况中:

  1. 字符集不匹配:数据库的字符集与应用程序或数据源的字符集不一致,导致无法正确处理特殊字符。
  2. 字符集不支持:数据库的字符集不支持存储特定的字符或字符序列,导致存储失败。
  3. 字符集设置错误:数据库在创建或配置时未正确设置字符集,导致不支持存储特殊字符。

解决方案

根据以上分析,我们可以采取以下措施来解决该问题:

1. 修改数据库字符集

首先,我们需要检查数据库字符集的配置。在MySQL中,可以使用以下命令查看和修改数据库的字符集配置:

sqlCopy code

-- 查看数据库字符集
SHOW VARIABLES LIKE 'character_set_database';

-- 修改数据库字符集(示例设置为utf8mb4)
ALTER DATABASE database_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

确保数据库的字符集与应用程序或数据源的字符集一致。常见的字符集有​​utf8​​、​​utf8mb4​​等。

2. 修改表字段字符集(推荐)

如果数据库字符集已正确配置,但仍然出现错误,可能是某个字段的字符集不支持存储特定的字符。我们可以通过修改表结构来解决该问题:

sqlCopy code

-- 修改表字段字符集(示例设置为utf8mb4)
ALTER TABLE `数据库名`.表名 MODIFY `字段名` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci COMMENT '字段注释';

3. 修改表字符集

如果涉及的字段比较多时,我们可以通过修改表结构来解决该问题:

sqlCopy code

-- 查看表字符集
SHOW FULL COLUMNS FROM table_name;

-- 修改表字符集(示例设置为utf8mb4)
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

使用以上命令可以查看表的字段和字符集信息,并修改表的字符集。

注意:修改整个表的字符集时,如果是关联查询的,关联表也要同时修改字符集,否则查询速度会很慢,因为字符集不匹配(utf8、utf8mb4)。

4. 修改连接字符集

如果以上两种方法都无法解决问题,可能是应用程序与数据库之间的连接字符集不匹配。我们可以通过修改应用程序的连接字符集来解决该问题。 对于使用JDBC连接MySQL数据库的Java应用程序,可以在连接URL中指定字符集:

javaCopy code

String url = "jdbc:mysql://localhost:3306/database_name?useUnicode=true&characterEncoding=UTF-8&useSSL=false";

通过在连接URL中添加​​useUnicode=yes&characterEncoding=UTF-8​​配置,可以确保应用程序与数据库之间的字符集匹配。

5.升级mysql驱动包

MySQL JDBC驱动版本5.1.47及以上支持utf8mb4,需要进行升级,如:8.0.15。

pom.xml

      <!--mysql驱动包-->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.15</version>
      </dependency>

JDBC驱动程序

  • com.mysql.jdbc.Driver 是mysql 8.0 以下版本使用的驱动包
  • com.mysql.cj.jdbc.Driver 是 mysql8.0 使用的驱动包

6.转换字符编码

如果以上方法都无法解决问题,我们可以考虑将特殊字符转换为数据库支持的编码。例如,将特殊字符转换为Unicode编码再存储到数据库中。 使用Java的​​StringEscapeUtils​​类可以将字符串转换为Java Unicode转义序列:

javaCopy code

import org.apache.commons.text.StringEscapeUtils;

String content = StringEscapeUtils.escapeJava(originalContent);

java示例

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class DatabaseTest {

    public static String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=UTC";
//    public static String driver = "com.mysql.jdbc.Driver";
    public static String driver = "com.mysql.cj.jdbc.Driver";
    public static String userName = "test";
    public static String password = "123";

    public static void main(String[] args) {
        dropTable();

        createTable();
        insertData();

        alterTable();
        insertData();

        selectData();

        dropTable();
    }

    /**
     * 删除表
     */
    public static void dropTable() {
        Connection conn = null;
        Statement stmt = null;
        try {
            Class.forName(driver);
            conn = DriverManager.getConnection(url, userName, password);
            stmt = conn.createStatement();
            // 创建表
            stmt.executeUpdate("DROP TABLE IF EXISTS comments");
            System.out.println("Table drop.");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (stmt != null) {
                    stmt.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 创建表
     */
    public static void createTable() {
        Connection conn = null;
        Statement stmt = null;
        try {
            Class.forName(driver);
            conn = DriverManager.getConnection(url, userName, password);
            stmt = conn.createStatement();
            // 创建表
            stmt.executeUpdate("CREATE TABLE comments (\n" +
                    "  `content` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci\n" +
                    ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci");
            System.out.println("Table create.");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (stmt != null) {
                    stmt.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 更改表结构
     */
    public static void alterTable() {
        Connection conn = null;
        Statement stmt = null;
        try {
            Class.forName(driver);
            conn = DriverManager.getConnection(url, userName, password);
            stmt = conn.createStatement();
            // 修改表结构
            stmt.executeUpdate("ALTER TABLE comments CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci");
            System.out.println("Table modified.");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (stmt != null) {
                    stmt.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 新增数据
     */
    public static void insertData(){
        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            Class.forName(driver);
            conn = DriverManager.getConnection(url, userName, password);
            // 插入数据
            String comment = "This is a comment with emoji 😊";
            pstmt = conn.prepareStatement("INSERT INTO comments (content) VALUES (?)");
            pstmt.setString(1, comment);
            pstmt.executeUpdate();
            System.out.println("Data inserted.");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (pstmt != null) {
                    pstmt.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 查询数据
     */
    public static void selectData(){
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            Class.forName(driver);
            conn = DriverManager.getConnection(url, userName, password);
            // 查询数据
            pstmt = conn.prepareStatement("SELECT * FROM comments");
            rs = pstmt.executeQuery();
            System.out.println("Data select.");

            if (rs.next()) {
                String content = rs.getString(1);
                System.out.println(content);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            try {
                if (rs != null) {
                    rs.close();
                }
                if (pstmt != null) {
                    pstmt.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

}

输出:

Table drop.
Table create.
java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x8A' for column 'content' at row 1
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
	at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
	at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
	at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:970)
	at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1109)
	at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1057)
	at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1377)
	at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1042)
	at com.enuo.DatabaseTest.insertData(DatabaseTest.java:140)
	at com.enuo.DatabaseTest.main(DatabaseTest.java:22)
Table modified.
Data inserted.
Data select.
This is a comment with emoji 😊
Table drop.

数据库,查看

结论

当遇到​​Caused by: java.sql.SQLException: Incorrect string value​​错误时,我们需要检查数据库字符集配置、表结构和连接字符集等因素,确保它们能够正确处理特殊字符。如有必要,我们可以转换特殊字符的编码,以适应数据库的要求。 通过以上方法,我们可以解决该错误并正常存储特殊字符或表情符号到数据库中,保证应用程序的正常运行。在开发过程中,我们应尽量避免存储不支持的特殊字符,以免引起其他兼容性问题。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值