尤記得好久之前,想存 emoj 表情到 mysql 中,須要額外的將 emoj 表情轉碼以後保存,每次讀取時,再解碼還原成一下;每次這種 sb 的操做,真心感受心塞,那麼有沒有辦法直接存呢?java
mysql 自己能夠經過選擇編碼集(如 utfbmb4)來支持 emoj 表情,然而今天遇到了一個至關鬼畜的問題,表中能夠直接寫入 emoj 表情,可是經過 spring boot 代碼塞入的 emoj 時,卻拋出異常:mysql
Caused by: java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x9D\xE6\xB1...' for column 'nick' at row 1 at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1084) ~[mysql-connector-java-5.1.30.jar:na] at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4232) ~[mysql-connector-java-5.1.30.jar:na] at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4164) ~[mysql-connector-java-5.1.30.jar:na] at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2615) ~[mysql-connector-java-5.1.30.jar:na] at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2776) ~[mysql-connector-java-5.1.30.jar:na] at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2838) ~[mysql-connector-java-5.1.30.jar:na] at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2082) ~[mysql-connector-java-5.1.30.jar:na]
接下來演示一下正確的使用姿式,以及致使上面問題的錯誤 case,避免你們重複採坑git
<!-- more -->github
接下來咱們的目標是能夠直接向 mysql 中讀取或寫入 emoj 表情spring
首先針對 mysql 表,須要指定字符集爲utfbmb4
sql
CREATE TABLE `Subscribe` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `email` varchar(140) NOT NULL DEFAULT '', `nick` varchar(30) NOT NULL DEFAULT '暱稱', `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '0 訂閱未激活, 1 訂閱已激活 , 2 取消訂閱', `created` int(13) NOT NULL DEFAULT '0' COMMENT '建立時間', `updated` int(13) NOT NULL DEFAULT '0' COMMENT '更新時間' PRIMARY KEY (`id`), UNIQUE KEY `email` (`email`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
上面直接設置表的字符集爲utf8mb4
,若是某個表已經存在,可是字符集不是 utf8mb4,這種 case 下咱們也能夠單獨的設置某個列的編碼以下springboot
ALTER TABLE `Subscribe` CHANGE `nick` `nick` VARCHAR(30) CHARACTER SET utf8mb4 NOT NULL DEFAULT '';
如上設置以後,咱們能夠直接在這個表中添加 emojbash
接下來進入正題,springboot 項目,如何支持 emoj 的插入;首先看一下項目依賴app
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> </dependencies> <build> <pluginManagement> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </pluginManagement> </build> <repositories> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/libs-snapshot-local</url> <snapshots> <enabled>true</enabled> </snapshots> </repository> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/libs-milestone-local</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> <repository> <id>spring-releases</id> <name>Spring Releases</name> <url>https://repo.spring.io/libs-release-local</url> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories>
咱們使用的是2.2.1.RELEASE
版本,請確保引入了依賴spring-boot-starter-jdbc
與 mysql-connector-java
dom
而後配置 db 相關屬性, application.properties
## DataSource spring.datasource.url=jdbc:mysql://127.0.0.1:3306/story?useUnicode=true&characterEncoding=UTF-8&useSSL=false spring.datasource.username=root spring.datasource.password=
而後就能夠愉快的進行測試了
@Slf4j @SpringBootApplication public class Application { public Application(JdbcTemplate jdbcTemplate) { log.warn("application start!!!"); // 插入emoj 表情 jdbcTemplate.update("insert into Subscribe (`email`, `nick`) values (?, ?)", UUID.randomUUID().toString() + "@t.com", "🐺狼"); List<Map<String, Object>> r = jdbcTemplate.queryForList("select * from Subscribe order by id desc limit 2"); log.info("r: {}", r); } public static void main(String[] args) { SpringApplication.run(Application.class); } }
實測結果以下
這個不已經插入成功了麼,那麼問題來了,本文開頭的那個異常是怎麼回事呢
出現文章開頭的問題,主要是因爲mysql-connector-java
的版本問題致使的,咱們來複現一下,首先將版本指定爲5.1.30
(由於咱們內部使用的就是這個版本,因此採坑了...)
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.30</version> </dependency>
其次須要在環境配置中,指定一下driver-class-name
spring.datasource.driver-class-name= com.mysql.jdbc.Driver
注意
這裏須要說明一下,在更高的mysql-connector-java
版本中,已經改爲com.mysql.cj.jdbc.Driver
這個類了;若是依舊配置上面的 Driver,在執行時會有一行提示
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
最後再次執行前面的測試代碼,異常就來了
在 mysql 中存入 emoj 表情的場景能夠說比較多了,畢竟 21 世紀了,不支持 emoj 的應用是沒有前途的;經過前面的 case,即介紹瞭如何正確的讓 springboot 應用支持 emoj 表情,也給出了一個因爲版本問題致使的坑
emoj 支持步驟
mysql-connector-java
版本,務必選擇比較新的版本,
springboot2.2.1.RELEASE
默認提供的版本爲8.0.18
5.1.30
則不支持 emoj 插入com.mysql.cj.jdbc.Driver
替換以前的com.mysql.jdbc.Driver
盡信書則不如,以上內容,純屬一家之言,因我的能力有限,不免有疏漏和錯誤之處,如發現 bug 或者有更好的建議,歡迎批評指正,不吝感激
下面一灰灰的我的博客,記錄全部學習和工做中的博文,歡迎你們前去逛逛