通过mysql工作台插入emoji可以工作,但不能通过java?

trnvg8h3  于 2021-06-21  发布在  Mysql
关注(0)|答案(0)|浏览(196)

通过mysql workbench查询,我能够在表中插入emoji,但前提是我首先设置了名称。

SET NAMES utf8mb4; //only need to do this once everytime i start the server
insert into testtable (testfield) values ('?'); //works!

但是,在java中执行相同的操作会导致异常:

java.sql.SQLException: Incorrect string value: '\xF0\x9F\x92\x96' for column 'testfield' at row 1

java :

public static void main(String[] args) {
  TestDao t = new TestDao();
  t.setNamesUtf8mb4(); //SET NAMES utf8mb4;
  t.insertTest("?"); //doesn't work :(
}

测试刀

public void setNamesUtf8mb4(){
    try(Connection conn = DBConnection.getConnection()){
        PreparedStatement pst = conn.prepareStatement("SET NAMES utf8mb4;");
           pst.executeUpdate();         
    } catch (SQLException e) {
        e.printStackTrace();
    }
}
public void insertTest(String test){
    try(Connection conn = DBConnection.getConnection()){
        PreparedStatement pst = conn.prepareStatement("insert into testtable (testfield) values (?);");
        pst.setString(1, test);
           pst.executeUpdate(); 
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

数据库连接:

public class DBConnection {
    private static String url = null;
    private static Connection conn = null;
     public static Connection getConnection(){
     try{
       Class.forName("com.mysql.jdbc.Driver");
       url = "jdbc:mysql://localhost:3306/testdb";
       conn = DriverManager.getConnection(url,"root","1234");
     }   catch (Exception e) {
            System.out.println(e);
        } 
     return conn;
     }
}

我的表和数据库的字符集和排序规则

mysql> SHOW FULL COLUMNS FROM testtable WHERE Field = 'testfield';

+-------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
| Field | Type         | Collation          | Null | Key | Default | Extra | Privileges                      | Comment |
+-------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
| testfield | varchar(191) | utf8mb4_unicode_ci | YES  |     | NULL    |       | select,insert,update,references |         |
+-------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
1 row in set (0.00 sec)

mysql> SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
+--------------------------+--------------------+
| Variable_name            | Value              |
+--------------------------+--------------------+
| character_set_client     | utf8mb4            |
| character_set_connection | utf8mb4            |
| character_set_database   | utf8mb4            |
| character_set_filesystem | binary             |
| character_set_results    | utf8mb4            |
| character_set_server     | utf8mb4            |
| character_set_system     | utf8               |
| collation_connection     | utf8mb4_unicode_ci |
| collation_database       | utf8mb4_unicode_ci |
| collation_server         | utf8mb4_unicode_ci |
+--------------------------+--------------------+
10 rows in set (0.00 sec)

我的.ini:

[client]
default-character-set=utf8mb4
[mysql]
no-beep=
default-character-set=utf8mb4
[mysqld]
character-set-client-handshake = FALSE
character_set_server=utf8mb4
collation_server=utf8mb4_unicode_ci
init-connect='SET NAMES utf8mb4'

我已尝试更改连接url:

url = "jdbc:mysql://localhost:3306/testdb?useUnicode=yes&characterEncoding=UTF-8"; //note: "=utf8mb4" isn't valid here

所有的想法,任何想法为什么这是不工作?为什么它只在mysql工作台上工作而不在java上工作?与连接器/j有关吗?
编辑
一条评论建议在同一个连接中设置名称,我试过了,似乎很管用。但这不是很低效吗?我不想执行死刑 set names 在每次插入或更新之前。。。当然有更好的方法吗?
这样做有效:

public void insertTest(String test){
    try(Connection conn = DBConnection.getConnection()){
    PreparedStatement pst = conn.prepareStatement("SET NAMES utf8mb4;"); //set names in same connection
               pst.executeUpdate(); 
        pst = conn.prepareStatement("insert into testtable (testfield) values (?);");
        pst.setString(1, test);
           pst.executeUpdate(); 
    } catch (SQLException e) {
        e.printStackTrace();
    }
}

编辑2
sql版本

mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.11    |

pom.xml文件

<dependency>
  <groupId>mysql</groupId>
  <artifactId>mysql-connector-java</artifactId>
  <version>8.0.11</version>
</dependency>

编辑3
项目的jdk版本是 jdk1.8.0_161 以及使用以下公式获得测试的十六进制(?):

public String toHex(String arg) {
    return String.format("%040x", new BigInteger(1, arg.getBytes()));
}

生产:
0000000000000000000003F
或使用以下方法进行测试:

static String stringToHex(String string) {
  StringBuilder buf = new StringBuilder(200);
  for (char ch: string.toCharArray()) {
    if (buf.length() > 0)
      buf.append(' ');
    buf.append(String.format("%04x", (int) ch));
  }
  return buf.toString();
}

生产:
d83d dc96型

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题