Oracle數據庫字符集爲WE8ISO8859P1存儲中文和Java讀寫展示

前言

之前《Oracle數據庫字符集爲WE8ISO8859P1存儲中文和客戶端程序展示中文問題》記錄了類似的問題。我們發現只要客戶端和服務端字符集一致,比如NLS_LANG=american_america.WE8ISO8859P1,客戶端程序也能夠正常用Oracle讀寫中文(Toad亂碼屬於自身問題)。

再次出現的現象

但是用Java SE客戶端程序(和C++或Delphi客戶端程序在同一臺計算機上)訪問該Oracle英文字符集數據庫。發現取到的中文字符還是亂碼 —— 是的,可執行程序通過設置一致的字符集解決了問題,對Java程序不管用。

分析

通過查閱資料,發現JDBC不再使用客戶端的NLS_LANG這個環境變量。
而是使用了客戶端系統的語言進行數據庫連接???

失敗嘗試1

jdbc thin vs jdbc oci
無論設置無需Oracle客戶端的thin模式,還是需要客戶端的oci模式,都無法解決這個問題。
網上很多文章比如這篇,寫的是 把 thin 改爲 oci 後,就用客戶端了,就可以讀取NLS_LANG環境變量了, 實際測試在Oracle11g下是不行的,依然亂碼。

失敗嘗試2

MySQL的方式並不適合Oracle數據庫,後面不能帶參數。

conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=utf8",

失敗嘗試3

看到JavaEE項目的同事這麼寫的:
後端在spring的配置文件配置數據據源時添加如下property

    <property name="ConnectionProperties">
    	<!-- 鏈接參數配置 “clientEncoding”和“serverEncoding”,分別指定數據庫客戶端和服務器端的字符編碼 Encoding Filter從這兩個參數獲取編碼 -->
    	<value>clientEncoding=GBK;serverEncoding=ISO-8859-1;</value>
    </property>

配置數據庫連接字符串如下:

jdbc:wrap-jdbc:filters=encoding:jdbc:oracle:thin:@IP地址:1521/orcl

但是JavaSE項目並沒有spring或其它框架……
同時JDBC表示並不認識wrap-jdbc是什麼。

解決

方案1:每句都自己轉碼(麻煩死了)。

new String(result.getString(col).getBytes("ISO8859-1"), "GBK") //讀數據集
new String(aValue.getBytes("GBK"), "ISO8859-1")	//寫入數據庫

方案2:使用阿里巴巴的Druid

官方定義:Druid是Java的數據庫連接池,能夠提供強大的監控和擴展功能。
阿里巴巴的《Druid簡介》。請注意阿里巴巴不是阿帕奇。。。

即使去掉違反廣告法的文字描述後,依然能感覺到很厲害!畢竟人形德魯伊能變熊/豹/獵豹/水下/飛行/鳥,並且喜歡荷蘭隊的年紀稍大一點的朋友也都知道,範尼是德魯伊呀。

pom.xml

<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
	<groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.1.22</version>
</dependency>

java

//驅動
//public static String driverClass = "oracle.jdbc.driver.OracleDriver";
public static String driverClass = "com.alibaba.druid.proxy.DruidDriver";
...
//連接字符串:
//String connurl = "jdbc:oracle:thin:@192.168.168.115:1521/testdb";
String connurl = "jdbc:wrap-jdbc:filters=encoding:jdbc:oracle:thin:@192.168.168.115:1521/testdb";
...
//設置屬性(包括用戶名密碼):
//畢竟咱沒有Spring框架可以設置編碼格式。
Properties info = new Properties();
info.setProperty("user","test");
info.setProperty("password","******");
info.setProperty("serverEncoding","ISO-8859-1"); //服務端編碼
info.setProperty("clientEncoding","GBK"); //客戶端編碼
conn = DriverManager.getConnection(connurl,info);
...

之後用正常的語句取數據,insert時也不用轉碼(綁定變量或直接拼字符串)。
是改老項目最方便的方法。

結論

客戶端和服務器都爲單字節字符集,操作系統支持中文顯示。
應用程序是可以顯示中文的。
但是Java SE程序只用標準JDBC是沒有簡單辦法的。

如果您知道用標準JDBC的解決辦法,請一定留言賜教啊!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章