common-jdbc說明
oracle使用西文數(shù)據(jù)庫時(shí),使用jdbc直接訪問得到的是亂碼,需要手工轉(zhuǎn)碼,雖然oraclejdbc的文檔表明似乎oci方式是
完全等同于客戶端方式,只要客戶端nls設(shè)置正確就可以正常存取,但是鄙人折騰一天都沒搞定。另外實(shí)驗(yàn)發(fā)現(xiàn),此種西文
數(shù)據(jù)庫情況,如果不轉(zhuǎn)碼,在jsp頁面輸出的話,由瀏覽器負(fù)責(zé)轉(zhuǎn)碼也可以保證輸入輸出正常,但是中間部分就沒法做單元
測試和一些值修改操作了。而且在我使用的wicket框架里面也無法這樣設(shè)置轉(zhuǎn)換。
最后還是絕定通過修補(bǔ)jdbc的方式來實(shí)現(xiàn)自動(dòng)轉(zhuǎn)碼,最初想法是反編譯oracle的jdbc, 對(duì)setString, getString, sql,進(jìn)行轉(zhuǎn)碼修補(bǔ),但是發(fā)現(xiàn)反編譯后的代碼有問題,修復(fù)工作量太大。再考慮這種方式會(huì)導(dǎo)致不容易升級(jí)jdbc,遂想用proxy的方式來實(shí)現(xiàn)一套jdbc殼,起初考慮省時(shí)間用p6spy的修改,后來搜索發(fā)現(xiàn)網(wǎng)絡(luò)強(qiáng)人[http://www.dling.com] 令少已經(jīng)干了同樣的事情了,就直接拿過來改了。
他主要是改了2個(gè)地方,一個(gè)是getString做了中文轉(zhuǎn)碼,而setString沒轉(zhuǎn)碼,只做了trim處理(trim的原因是oracle的char的問題。 和通常的理解不同的是, char類型并不比varchar2更有效率。 在現(xiàn)在版本的oracle中,char實(shí)際是一種偽裝的varchar2. 保留char可能是為了和以前版本兼容。而char本身在使用上有很多問題,主要是他會(huì)自動(dòng)補(bǔ)齊字符串,導(dǎo)致比對(duì)時(shí)候容易犯錯(cuò)。所以建議9i以后的數(shù)據(jù)庫今可能使用varchar2代替char),但是我實(shí)驗(yàn)有點(diǎn)問題。
相對(duì)令少的修改:
1. 對(duì)rs.getObject方法也進(jìn)行了判斷,是String對(duì)象就轉(zhuǎn)碼。另外還修補(bǔ)了幾個(gè)update方法。
2. 修補(bǔ)了stamment 和pstatemnt 的setString和 setObject,進(jìn)行了轉(zhuǎn)碼
3. 對(duì)所有會(huì)調(diào)用sql的地方進(jìn)行了轉(zhuǎn)碼,防止sql中含有中文的情況。
基本轉(zhuǎn)碼方式是 取數(shù)據(jù)時(shí) 從系統(tǒng)字符集(8859-1)轉(zhuǎn)換到gbk, 存的時(shí)候反之。
配置參看單元測試程序代碼。
@Before

public void setUp() throws Exception
{
DriverManager.registerDriver(new com.dingl.jdbc.CommonDriver());

conn = DriverManager.getConnection(
"jdbc:common/dbtype=oracle&host=localhost&port=1521&dbname=ora9i&useTrim=yes&charset=gbk&os-charset=iso8859-1", "system", "manager1");
}


可憐某公司CTO居然看不懂proxy模式,硬是冤枉俺說俺寫的jdbc 不如oracle自己帶的,拖慢了系統(tǒng)速度,該牛人居然測試出有10倍的速度差異,可憐丫。
東西在這,有用的可以拿去,反正是取之于民用之于民。
/Files/ghostdog/common-jdbc-proxy.zip