數據庫字符國際化是大家提問最多的問題
例如MySQL數據庫大家可能在JDBC
URL添加useUnicode=true&CharacterEncoding=GBK作為中文支持的基本條件
但這有時破壞了數據的完整性
如果某些人粗心大意
就會導致數據編碼錯誤
產生亂碼
因此
我們需要一些手段在程序內部進行編碼處理
人們一般通過在應用上使用 String(bytes:byte[]
enc:String)/String
getBytes(enc:String)進行字符串編解碼
這樣做雖然易懂
但是如果遇到大字段表格
手動編碼時費時費力
我的方法
通過研究JDK類庫
可以感覺到多層處理機制在數據處理上的優越性
我們完全有可能在數據庫上建立一個中間層用於字符的國際化處理
我就是這麼做的
仔細研究一下JDBC操作數據庫出現字符編碼問題的根源
很容易發現多數情況是ResultSet的幾個String方法在作怪
因此我們就完全可以編寫一個ResultSet中間層進行國際化處理
源碼如下
public class I
nResultSet implements ResultSet{ private String encoding; private ResultSet rs; public I
nResultSet(ResultSet rs
String encoding) throws java
io
UnsupportedEncodingException{ //檢查該編碼名稱是否被系統支持
getBytes(encoding); this
rs = rs; this
encoding = encoding; } … … //以下幾個方法是進行String字符串的重編碼
public String getString(int index) throws SQLException{ String data = null; try{ data = new String(rs
getBytes(index)
encoding); }catch(java
io
UnsupportedEncodingException uee){} } public String getString(Stirng field) throws SQLException{ String data = null; try{ data = new String(rs
getBytes(field)
encoding); }catch(java
io
UnsupportedEncodingException uee){} } public void updateString(int index
String value) throws SQLException{ try{ rs
updateBytes(index
value
getBytes(encoding)); }catch(java
io
UnsupportedEncodingException uee){} } public void updateString(String field
String value) throws SQLException{ try{ rs
updateBytes(field
value
getBytes(encoding)); }catch(java
io
UnsupportedEncodingException uee){} } … …}
可以看出
所有的String操作都使用特定編碼的字節數組進行存取
這樣通過定義encoding的值實現數據庫存取數據編碼的一致性
且encoding完全可以通過在配置信息中動態定義
同時
上面的程序又可以解決一些固有的字符串處理問題
例如控制符如\r\n導入到數據庫中很有可能被解析為\\r\\n使其不能換行
通過字節數組操作
就可以解決這個問題
這樣像文章固有格式就可以完整地保留下來而不需要進行額外轉換操作
結論
通過多層處理機制使用中間層對數據庫數據進行層層處理可使處理環節之間形成松耦合關系
從而可以進行有效的控制
下面給一個使用動態代理進行字符控制的代碼(原創):
package com
yipsilon
crocodile
database;import java
sql
ResultSet;import java
lang
reflect
InvocationHandler;import java
lang
reflect
Method;import java
io
UnsupportedEncodingException;/** * 作者 yipsilon * 如要轉載
請通知作者 */public class I
nResultSetHandler implements InvocationHandler{ private ResultSet rs; private String encoding; public I
nResultSetHandler(ResultSet rs
String encoding) throws UnsupportedEncodingException{ this
rs = rs;
getBytes(encoding); this
encoding = encoding; } public Object invoke(Object proxy
Method method
Object[] args) throws Throwable{ String methodName = method
getName(); if(methodName
equals(
getString
)){ Object obj = args[
]; if(obj instanceof Integer){ return decodeString(rs
getBytes(((Integer)obj)
intValue())
encoding); }else{ return decodeString(rs
getBytes((String)obj)
encoding); } }else if(methodName
equals(
updateString
)){ Object obj = args[
]; if(obj instanceof Integer){ rs
updateBytes(((Integer)obj)
intValue()
encodeString((String)args[
]
encoding)); }else{ rs
updateBytes((String)obj
encodeString((String)args[
]
encoding)); } return null; } return method
invoke(rs
args); } private String decodeString(byte[] bytes
String enc){ try{ return new String(bytes
enc); } catch(UnsupportedEncodingException uee){ return new String(bytes); } } private byte[] encodeString(String str
String enc){ try{ return str
getBytes(enc); } catch(UnsupportedEncodingException uee){ return str
getBytes(); } }}
使用時調用:
ResultSet rs =
; //原始的ResultSet結果集String encoding =
GBK
; //字符編碼(ResultSet)Proxy
newProxyInstance(rs
getClass()
getClassLoader()
rs
getClass()
getInterfaces()
new I
nResultSetHandler(rs
encoding));
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26086.html