總結寫在前面,
總結:
當Java通過jdbc鏈接mysql插入中文時,要保證程序可以正常執行,而且插入的中文不會亂碼,
- mysql服務器端,對數據表(不是數據庫)的編碼設置,要保證是支持中文的,例如gbk, gb2312, utf-8
- jdbc的連接配置,要開啟useUnicode=true,並且要設置一個支持中文的編碼,不需要跟mysql表的編碼保持一致,只需要支持中文就行。例如characterEncoding=utf8
- 本身的Java文件的編碼需要支持中文
=============================================================================
剛學習JDBC,今天在調試代碼的時候發現明明在公司的時候還能正常執行的插入語句,回來就不行了,測試代碼是這樣的。
數據庫配置文件 mysql.ini
1 driver=com.mysql.jdbc.Driver 2 url=jdbc:mysql://127.0.0.1:3306/dedecms 3 user=root 4 pass=
測試代碼
1 package db; 2 3 import java.io.FileInputStream; 4 import java.io.FileNotFoundException; 5 import java.io.IOException; 6 import java.sql.Connection; 7 import java.sql.DriverManager; 8 import java.sql.SQLException; 9 import java.sql.Statement; 10 import java.util.Properties; 11 12 public class Test { 13 private String driver; 14 private String url; 15 private String user; 16 private String pass; 17 public void initParam(String paramFile) throws FileNotFoundException, IOException, ClassNotFoundException { 18 Properties prop = new Properties(); 19 prop.load(new FileInputStream(paramFile)); 20 driver = prop.getProperty("driver"); 21 url = prop.getProperty("url"); 22 user = prop.getProperty("user"); 23 pass = prop.getProperty("pass"); 24 Class.forName(driver); 25 } 26 27 public int insertData(String sql) throws SQLException { 28 try ( 29 Connection conn = DriverManager.getConnection(url, user, pass); 30 Statement stmt = conn.createStatement()) { 31 return stmt.executeUpdate(sql); 32 } 33 } 34 35 public static void main(String[] args) throws FileNotFoundException, ClassNotFoundException, IOException, SQLException { 36 Test t = new Test(); 37 t.initParam("mysql.ini"); 38 t.insertData("insert into jdbc_test (jdbc_name, jdbc_desc) values ('測試標題','測試內容');"); 39 System.out.println("ok"); 40 } 41 42 }
本來在公司還能執行的,拿回家新建了數據庫,就不行了,報錯如下,
1 Exception in thread "main" com.mysql.jdbc.MysqlDataTruncation: Data truncation: Incorrect string value: '\xCE\xE4\xBA\xBA\xB5\xD8...' for column 'jdbc_name' at row 1 2 at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3513) 3 at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3447) 4 at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1951) 5 at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2101) 6 at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2548) 7 at com.mysql.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1605) 8 at com.mysql.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1524) 9 at db.ExecuteSQL.insertData(ExecuteSQL.java:47) 10 at db.ExecuteSQL.main(ExecuteSQL.java:119)
考慮到插入了中文,在網上搜索了mysql的jdbc的url配置方法
1 url=jdbc:mysql://127.0.0.1:3306/dedecms?useUnicode=true&characterEncoding=utf8
即需要開啟useUnicode=true並設置一種字符集,但是發現設置之后還是會出現上面的錯誤,於是又嘗試修改了Eclipse文檔的字符集,
即在preferences->general->workspace->text file encoding下選擇UTF-8,使java文件與jdbc鏈接配置的編碼一致,
然而發現這么設置之后,已然會出現上面的問題,想想大概是mysql數據庫本身的設置不對,於是又更改下面的配置(用的phpMyAdmin做mysql客戶端)
找到我當前的數據庫,將排序規則改為了 utf8_unicode_ci
再次執行程序,發現問題依然存在,於是又折騰了半天,發現不僅僅是數據庫可以修改排序規則,單個表格也可以修改排序規則,
將表格的排序規則也改成 utf8_unicode_ci ,並且勾選 Change all column collations ,
再次執行程序,終於可以看到數據正常插入了!
程序測試結果,
表內容
不過后來又發現一個有趣的事情,就是無論mysql服務器的表設置為什么編碼,只要在jdbc鏈接的時候也選擇同樣的編碼,程序就可以執行成功,
只不過如果編碼不支持中文的話,數據表里就會出現亂碼,例如這樣,
mysql數據表是拉丁編碼
mysql鏈接字符串也用拉丁編碼
1 url=jdbc:mysql://127.0.0.1:3306/dedecms?useUnicode=true&characterEncoding=latin1
java文件編碼默認
然后發現可以執行,
但是數據表里全是亂碼,
而一旦將數據表里的編碼修改成支持中文的編碼,比如gb2312
並且將mysql jdbc的鏈接也修改成支持中文的編碼, gb2312, gbk, utf8中的任何一個都行,並不需要跟數據表編碼一致,
1 url=jdbc:mysql://127.0.0.1:3306/dedecms?useUnicode=true&characterEncoding=utf8
當然,eclipse的文件編碼也必須支持中文(否則根本無法保存含有中文的文件),比如utf-8
這樣的話,就能正常執行程序,而且插入數據表的中文也不會亂碼了
所以,在創建表的時候順便指定字符集是很重要的,像這樣,
1 create table jdbc_test (jdbc_id int auto_increment primary key, jdbc_name varchar(255), jdbc_desc text) DEFAULT CHARSET=utf8;
總結:
當Java通過jdbc鏈接mysql插入中文時,要保證程序可以正常執行,而且插入的中文不會亂碼,
- mysql服務器端,對數據表的編碼設置,要保證是支持中文的,例如gbk, gb2312, utf-8
- jdbc的連接配置,要開啟useUnicode=true,並且要設置一個支持中文的編碼,不需要跟mysql表的編碼保持一致,只需要支持中文就行。例如characterEncoding=utf8
- 本身的Java文件的編碼需要支持中文
ps:
關於這個問題,今天在CSDN上看到一個喜歡鑽研的人,研究了一下jdbc數據傳輸過程(tcp),並做了抓包分析,頗有幫助,
http://blog.csdn.net/dslztx/article/details/47070475