国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

[原創] Java數據庫字符國際化

2019-11-18 11:20:41
字體:
來源:轉載
供稿:網友

數據庫字符國際化是大家提問最多的問題,例如MySQL數據庫大家可能在JDBC-URL添加useUnicode=true&CharacterEncoding=GBK作為中文支持的基本條件。但這有時破壞了數據的完整性,假如某些人粗心大意,就會導致數據編碼錯誤,產生亂碼。因此,我們需要一些手段在程序內部進行編碼處理。人們一般通過在應用上使用 String(bytes:byte[], enc:String)/String.getBytes(enc:String)進行字符串編解碼,這樣做雖然易懂,但是假如碰到大字段表格,手動編碼時費時費力。

我的方法:通過研究JDK類庫,可以感覺到多層處理機制在數據處理上的優越性。我們完全有可能在數據庫上建立一個中間層用于字符的國際化處理,我就是這么做的。仔細研究一下JDBC操作數據庫出現字符編碼問題的根源,很輕易發現多數情況是ResultSet的幾個String方法在作怪,因此我們就完全可以編寫一個ResultSet中間層進行國際化處理,源碼如下:


public class I18nResultSet implements ResultSet{
PRivate String encoding;
private ResultSet rs;
public I18nResultSet(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 I18nResultSetHandler implements InvocationHandler{
private ResultSet rs;
private String encoding;

public I18nResultSetHandler(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[0];
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[0];
if(obj instanceof Integer){
rs.updateBytes(((Integer)obj).intValue(), encodeString((String)args[1], encoding));
}else{
rs.updateBytes((String)obj, encodeString((String)args[1], 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 I18nResultSetHandler(rs, encoding));



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 玉田县| 宁南县| 新昌县| 广河县| 贵州省| 乐平市| 达日县| 广水市| 玛沁县| 揭西县| 灌阳县| 宣汉县| 泾阳县| 库车县| 清苑县| 南宁市| 樟树市| 大城县| 聂拉木县| 康乐县| 邵武市| 朝阳区| 休宁县| 吴堡县| 苏尼特右旗| 凭祥市| 梁平县| 西安市| 文水县| 施甸县| 南开区| 三原县| 扶沟县| 吉首市| 庐江县| 房山区| 科技| 许昌市| 伊宁市| 林口县| 吉水县|