通过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型
暂无答案!
目前还没有任何答案,快来回答吧!