*****************web開發(fā)的問(wèn)題匯總********************
2. Hibernate優(yōu)化問(wèn)題。如何優(yōu)化數(shù)據(jù)庫(kù)訪問(wèn),使程序訪問(wèn)數(shù)據(jù)庫(kù)更優(yōu)化。
初用HIBERNATE的人也許都遇到過(guò)性能問(wèn)題,實(shí)現(xiàn)同一功能,用HIBERNATE與用JDBC性能相差十幾倍很正常,如果不及早調(diào)整,很可能影響整個(gè)項(xiàng)目的進(jìn)度。
大體上,對(duì)于HIBERNATE性能調(diào)優(yōu)的主要考慮點(diǎn)如下:
* 數(shù)據(jù)庫(kù)設(shè)計(jì)調(diào)整
* HQL優(yōu)化
* API的正確使用(如根據(jù)不同的業(yè)務(wù)類型選用不同的集合及查詢API)
* 主配置參數(shù)(日志,查詢緩存,fetch_size, batch_size等)
* 映射文件優(yōu)化(ID生成策略,二級(jí)緩存,延遲加載,關(guān)聯(lián)優(yōu)化)
* 一級(jí)緩存的管理
* 針對(duì)二級(jí)緩存,還有許多特有的策略
* 事務(wù)控制策略。
1、 數(shù)據(jù)庫(kù)設(shè)計(jì)
a) 降低關(guān)聯(lián)的復(fù)雜性
b) 盡量不使用聯(lián)合主鍵
c) ID的生成機(jī)制,不同的數(shù)據(jù)庫(kù)所提供的機(jī)制并不完全一樣
d) 適當(dāng)?shù)娜哂鄶?shù)據(jù),不過(guò)分追求高范式
2、 HQL優(yōu)化
HQL如果拋開它同HIBERNATE本身一些緩存機(jī)制的關(guān)聯(lián),HQL的優(yōu)化技巧同普通的SQL優(yōu)化技巧一樣,可以很容易在網(wǎng)上找到一些經(jīng)驗(yàn)之談。
3、 主配置
a) 查詢緩存,同下面講的緩存不太一樣,它是針對(duì)HQL語(yǔ)句的緩存,即完全一樣的語(yǔ)句再次執(zhí)行時(shí)可以利用緩存數(shù)據(jù)。但是,查詢緩存在一個(gè)交易系統(tǒng)(數(shù)據(jù)變更頻繁,查詢條件相同的機(jī)率并不大)中可能會(huì)起反作用:它會(huì)白白耗費(fèi)大量的系統(tǒng)資源但卻難以派上用場(chǎng)。
b) fetch_size,同JDBC的相關(guān)參數(shù)作用類似,參數(shù)并不是越大越好,而應(yīng)根據(jù)業(yè)務(wù)特征去設(shè)置
c) batch_size同上。
d) 生產(chǎn)系統(tǒng)中,切記要關(guān)掉SQL語(yǔ)句打印。
4、 緩存
a) 數(shù)據(jù)庫(kù)級(jí)緩存:這級(jí)緩存是最高效和安全的,但不同的數(shù)據(jù)庫(kù)可管理的層次并不一樣,比如,在ORACLE中,可以在建表時(shí)指定將整個(gè)表置于緩存當(dāng)中。
b) SESSION緩存:在一個(gè)HIBERNATE SESSION有效,這級(jí)緩存的可干預(yù)性不強(qiáng),大多于HIBERNATE自動(dòng)管理,但它提供清除緩存的方法,這在大批量增加/更新操作是有效的。比如,同時(shí)增加十萬(wàn)條記錄,按常規(guī)方式進(jìn)行,很可能會(huì)發(fā)現(xiàn)OutofMemeroy的異常,這時(shí)可能需要手動(dòng)清除這一級(jí)緩存:Session.evict以及Session.clear
c) 應(yīng)用緩存:在一個(gè)SESSIONFACTORY中有效,因此也是優(yōu)化的重中之重,因此,各類策略也考慮的較多,在將數(shù)據(jù)放入這一級(jí)緩存之前,需要考慮一些前提條件:
i. 數(shù)據(jù)不會(huì)被第三方修改(比如,是否有另一個(gè)應(yīng)用也在修改這些數(shù)據(jù)?)
ii. 數(shù)據(jù)不會(huì)太大
iii. 數(shù)據(jù)不會(huì)頻繁更新(否則使用CACHE可能適得其反)
iv. 數(shù)據(jù)會(huì)被頻繁查詢
v. 數(shù)據(jù)不是關(guān)鍵數(shù)據(jù)(如涉及錢,安全等方面的問(wèn)題)。
緩存有幾種形式,可以在映射文件中配置:read-only(只讀,適用于很少變更的靜態(tài)數(shù)據(jù)/歷史數(shù)據(jù)),nonstrict-read-write,read-write(比較普遍的形式,效率一般),transactional(JTA中,且支持的緩存產(chǎn)品較少)
d) 分布式緩存:同c)的配置一樣,只是緩存產(chǎn)品的選用不同,在目前的HIBERNATE中可供選擇的不多,oscache, jboss cache,目前的大多數(shù)項(xiàng)目,對(duì)它們的用于集群的使用(特別是關(guān)鍵交易系統(tǒng))都持保守態(tài)度。在集群環(huán)境中,只利用數(shù)據(jù)庫(kù)級(jí)的緩存是最安全的。
5、 延遲加載
a) 實(shí)體延遲加載:通過(guò)使用動(dòng)態(tài)代理實(shí)現(xiàn)
b) 集合延遲加載:通過(guò)實(shí)現(xiàn)自有的SET/LIST,HIBERNATE提供了這方面的支持
c) 屬性延遲加載:
6、 方法選用
a) 完成同樣一件事,HIBERNATE提供了可供選擇的一些方式,但具體使用什么方式,可能用性能/代碼都會(huì)有影響。顯示,一次返回十萬(wàn)條記錄(List/Set/Bag/Map等)進(jìn)行處理,很可能導(dǎo)致內(nèi)存不夠的問(wèn)題,而如果用基于游標(biāo)(ScrollableResults)或Iterator的結(jié)果集,則不存在這樣的問(wèn)題。
b) Session的load/get方法,前者會(huì)使用二級(jí)緩存,而后者則不使用。
c) Query和list/iterator,如果去仔細(xì)研究一下它們,你可能會(huì)發(fā)現(xiàn)很多有意思的情況,二者主要區(qū)別(如果使用了Spring,在HibernateTemplate中對(duì)應(yīng)find,iterator方法):
i. list只能利用查詢緩存(但在交易系統(tǒng)中查詢緩存作用不大),無(wú)法利用二級(jí)緩存中的單個(gè)實(shí)體,但list查出的對(duì)象會(huì)寫入二級(jí)緩存,但它一般只生成較少的執(zhí)行SQL語(yǔ)句,很多情況就是一條(無(wú)關(guān)聯(lián))。
ii. iterator則可以利用二級(jí)緩存,對(duì)于一條查詢語(yǔ)句,它會(huì)先從數(shù)據(jù)庫(kù)中找出所有符合條件的記錄的ID,再通過(guò)ID去緩存找,對(duì)于緩存中沒(méi)有的記錄,再構(gòu)造語(yǔ)句從數(shù)據(jù)庫(kù)中查出,因此很容易知道,如果緩存中沒(méi)有任何符合條件的記錄,使用iterator會(huì)產(chǎn)生N+1條SQL語(yǔ)句(N為符合條件的記錄數(shù))
iii. 通過(guò)iterator,配合緩存管理API,在海量數(shù)據(jù)查詢中可以很好的解決內(nèi)存問(wèn)題,如:
while(it.hasNext()){
YouObject object = (YouObject)it.next();
session.evict(youObject);
sessionFactory.evice(YouObject.class, youObject.getId());
}
如果用list方法,很可能就出OutofMemory錯(cuò)誤了。
iv. 通過(guò)上面的說(shuō)明,我想你應(yīng)該知道如何去使用這兩個(gè)方法了。
7、 集合的選用
在HIBERNATE 3.1文檔的“19.5. Understanding Collection performance”中有詳細(xì)的說(shuō)明。
8、 事務(wù)控制
事務(wù)方面對(duì)性能有影響的主要包括:事務(wù)方式的選用,事務(wù)隔離級(jí)別以及鎖的選用
a) 事務(wù)方式選用:如果不涉及多個(gè)事務(wù)管理器事務(wù)的話,不需要使用JTA,只有JDBC的事務(wù)控制就可以。
b) 事務(wù)隔離級(jí)別:參見標(biāo)準(zhǔn)的SQL事務(wù)隔離級(jí)別
c) 鎖的選用:悲觀鎖(一般由具體的事務(wù)管理器實(shí)現(xiàn)),對(duì)于長(zhǎng)事務(wù)效率低,但安全。樂(lè)觀鎖(一般在應(yīng)用級(jí)別實(shí)現(xiàn)),如在HIBERNATE中可以定義VERSION字段,顯然,如果有多個(gè)應(yīng)用操作數(shù)據(jù),且這些應(yīng)用不是用同一種樂(lè)觀鎖機(jī)制,則樂(lè)觀鎖會(huì)失效。因此,針對(duì)不同的數(shù)據(jù)應(yīng)有不同的策略,同前面許多情況一樣,很多時(shí)候我們是在效率與安全/準(zhǔn)確性上找一個(gè)平衡點(diǎn),無(wú)論如何,優(yōu)化都不是一個(gè)純技術(shù)的問(wèn)題,你應(yīng)該對(duì)你的應(yīng)用和業(yè)務(wù)特征有足夠的了解。
9、 批量操作
即使是使用JDBC,在進(jìn)行大批數(shù)據(jù)更新時(shí),BATCH與不使用BATCH有效率上也有很大的差別。我們可以通過(guò)設(shè)置batch_size來(lái)讓其支持批量操作。
舉個(gè)例子,要批量刪除某表中的對(duì)象,如“delete Account”,打出來(lái)的語(yǔ)句,會(huì)發(fā)現(xiàn)HIBERNATE找出了所有ACCOUNT的ID,再進(jìn)行刪除,這主要是為了維護(hù)二級(jí)緩存,這樣效率肯定高不了,在后續(xù)的版本中增加了bulk delete/update,但這也無(wú)法解決緩存的維護(hù)問(wèn)題。也就是說(shuō),由于有了二級(jí)緩存的維護(hù)問(wèn)題,HIBERNATE的批量操作效率并不盡如人意!
3. 網(wǎng)站是動(dòng)態(tài)的,需要頻繁訪問(wèn)數(shù)據(jù)庫(kù),如何提高訪問(wèn)速度,減少服務(wù)器壓力?
提供JDBC數(shù)據(jù)庫(kù)鏈接池共享,大大降低數(shù)據(jù)庫(kù)壓力;
智能動(dòng)態(tài)HTML,大大減少網(wǎng)絡(luò)數(shù)據(jù)流量;
海量數(shù)據(jù)優(yōu)化,大大提高登錄和訪問(wèn)速度;
用戶界面和數(shù)據(jù)緩存,大大提高登錄速度;
多層次體系結(jié)構(gòu),支持多個(gè)應(yīng)用程序服務(wù)器并行,大大提高系統(tǒng)伸縮性,并發(fā)訪問(wèn)用戶數(shù)目和數(shù)據(jù)安全性
4. 搜索引擎優(yōu)化,如何提高網(wǎng)站排名。優(yōu)化有哪些具體技術(shù)措施?
網(wǎng)站結(jié)構(gòu)設(shè)計(jì)中面向搜索引擎的優(yōu)化注意事項(xiàng)包括:
1)鏈接引用的重要性
a.以量取勝:不一定加入傳統(tǒng)門戶網(wǎng)站的分類目錄才是網(wǎng)站推廣,來(lái)自其他網(wǎng)站的任何反相鏈接都是有用的
b. 以質(zhì)取勝:被PageRank高的網(wǎng)站引用能更快地提高PageRank
c. 了解搜索引擎的"價(jià)值觀":不要通過(guò)Link Farm提高自身的站點(diǎn)排名:Google會(huì)懲罰那些主動(dòng)鏈接到Link Farm站點(diǎn)以提高自身排名站點(diǎn),相應(yīng)站點(diǎn)的頁(yè)面將不會(huì)被收入到索引中。但如果你的頁(yè)面被別的Link Farm鏈接了也不必?fù)?dān)心,因?yàn)檫@種被動(dòng)的鏈接是不會(huì)被懲罰的。
d. 不要吝嗇給其他網(wǎng)站的鏈接:如果一個(gè)網(wǎng)頁(yè)只有大量的進(jìn)入鏈接,而缺乏導(dǎo)出鏈接,也會(huì)被搜索引擎認(rèn)為是沒(méi)有價(jià)值的站點(diǎn)。
2)如何突出關(guān)鍵詞:網(wǎng)頁(yè)標(biāo)題、主題的設(shè)計(jì)
a.Theme Engine正在逐步超過(guò)PR,成為結(jié)果排序中更主要的因素
b.不要空著標(biāo)題:空著<title></title>無(wú)異于浪費(fèi)了最有價(jià)值的一塊陣地
c. 標(biāo)題長(zhǎng)度和內(nèi)容:不要過(guò)長(zhǎng),一般在40個(gè)字(80個(gè)字節(jié))以內(nèi),并充分突出關(guān)鍵詞的比重
d. 如果網(wǎng)頁(yè)很多的話,盡量使用不同的網(wǎng)頁(yè)標(biāo)題,爭(zhēng)取讓自己網(wǎng)站的內(nèi)容更多的進(jìn)入搜索引擎索引范圍
e. 除了<title></title>外,還可以用<h1></h1>標(biāo)題行突出內(nèi)容主題, 加強(qiáng)標(biāo)題的效果
3)頁(yè)面及站點(diǎn)結(jié)構(gòu)設(shè)計(jì)注意事項(xiàng)
a. 靜態(tài)鏈接: 大部分搜索引擎都認(rèn)為靜態(tài)鏈接的網(wǎng)頁(yè)是優(yōu)質(zhì)網(wǎng)頁(yè),Google在優(yōu)先抓取索引的網(wǎng)頁(yè)中70%以上是不帶參數(shù)鏈接的靜態(tài)網(wǎng)頁(yè)。而且即使同樣的內(nèi)容,靜態(tài)網(wǎng)頁(yè)也 會(huì)比動(dòng)態(tài)網(wǎng)頁(yè)權(quán)重高
b. 能夠進(jìn)入Google索引的頁(yè)面數(shù)量越多越好
c. 網(wǎng)站目錄結(jié)構(gòu)要扁平,因?yàn)槊可钜患?jí)目錄,PAGERANK降低1-2個(gè)檔次。假設(shè)首頁(yè)是3,其子可能目錄就是1了,更深可能就無(wú)法列入評(píng)級(jí)范圍了。
d. 表現(xiàn)和內(nèi)容的分離:“綠色”網(wǎng)頁(yè)
網(wǎng)頁(yè)中的javascript和css盡可能和網(wǎng)頁(yè)分離,一方面提高代碼重用度(也方便頁(yè)面緩存),另外一方面,由于有效內(nèi)容占網(wǎng)頁(yè)長(zhǎng)度的百分比高,也能提高相關(guān)關(guān)鍵詞在頁(yè)面中的比重也增加了。總之,應(yīng)該鼓勵(lì)遵循w3c的規(guī)范,使用更規(guī)范的XHTML和XML作為顯示格式便于內(nèi)容更長(zhǎng)時(shí)間的保存。
e. 讓所有的頁(yè)面都有能夠快速入口:站點(diǎn)地圖, 方便網(wǎng)頁(yè)爬蟲(spider)快速遍歷網(wǎng)站所有需要發(fā)布的內(nèi)容。如果首頁(yè)就是用Flash或圖片進(jìn)入的話,無(wú)異于將搜索引擎拒之門外,除了UI設(shè)計(jì)的用戶 友好外,spider friendly也是非常重要的
f. 保持網(wǎng)站自身的健康:經(jīng)常利用壞 鏈檢查工具檢查網(wǎng)站中是否有死鏈
g. 保持網(wǎng)頁(yè)內(nèi)容/鏈接的穩(wěn)定性和持久性:在搜索引擎索引中網(wǎng)頁(yè)存在的歷史也是一個(gè)比較重要的因素,而且歷史比較久的網(wǎng)頁(yè)被鏈接的幾率越高。為了 保證自己網(wǎng)頁(yè)能夠被比較持久的被其他網(wǎng)站的頁(yè)面引用,如果自己網(wǎng)頁(yè)中有鏈接更新時(shí),最好能保留舊的頁(yè)面并做好鏈接轉(zhuǎn)向,以保持內(nèi)容的連續(xù)性。
h. 文件類型因素:Google有對(duì)PDF, Word(Power Point, Excel), PS文檔的索引能力,由于這種文檔的內(nèi)容比一般的HTML經(jīng)過(guò)了更多的整理,學(xué)術(shù)價(jià)值一般比較高,所以這些類型的文檔天生就比一般的HTML類型的文檔 PageRank要高。因此,對(duì)于比較重要的文檔:技術(shù)白皮書,F(xiàn)AQ,安裝文檔等建議使用PDF PS等高級(jí)格式存取,這樣在搜索結(jié)果中也能獲得比較靠前的位zhi點(diǎn)訪問(wèn)統(tǒng)計(jì)的重要性等;,的設(shè)計(jì)
4)以及站點(diǎn)訪問(wèn)統(tǒng)計(jì)的重要性等
5)Google的站點(diǎn)設(shè)計(jì)指南
1.Make a site with a clear hierarchy and text links. Every page should be reachable from at least one static text link. 讓網(wǎng)站有著清晰的結(jié)構(gòu)和文本鏈接,所有的頁(yè)面至少要有一個(gè)靜態(tài)文本鏈接入口
批注:盡量不要用圖片和JAVASCRIPT
2.Offer a site map to your users with links that point to the important parts of your site. If the site map is larger than 100 or so links, you may want to break the site map into separate pages.
為用戶提供一個(gè)站點(diǎn)地圖:轉(zhuǎn)向網(wǎng)站的重要部分。如果站點(diǎn)地圖頁(yè)面超過(guò)100個(gè)鏈接,則需要將頁(yè)面分成多個(gè)頁(yè)面。
批注:索引頁(yè)不要超過(guò)100個(gè)鏈接:SPIDER只考慮頁(yè)面中頭100個(gè)鏈接
3.Create a useful, information-rich site and write pages that clearly and accurately describe your content.
用一些有用的,信息量豐富的站點(diǎn),清晰并正確的描述你的信息。
4.Think about the words users would type to find your pages, and make sure that your site actually includes those words within it.
想像用戶可能用來(lái)找到你的關(guān)鍵詞,并保證這些關(guān)鍵詞在網(wǎng)站中出現(xiàn)。
批注:少用“最大”,“最好”之類的形容詞,用用戶最關(guān)心的詞,比如:下載,歌星名字,而不是一些抽象名詞。
5.Try to use text instead of images to display important names, content, or links. The Google crawler doesn't recognize text contained in images.
盡可能使用文本,而不是圖片顯示重要的名稱,內(nèi)容和鏈接。GOOGLE的機(jī)器人不認(rèn)識(shí)圖片中的文字。
6.Make sure that your TITLE and ALT tags are descriptive and accurate.
保證:頁(yè)面的TITLE和ALT標(biāo)記正確的精確描述
7.Check for broken links and correct HTML.
檢查壞鏈并修正這些HTML錯(cuò)誤。
8.If you decide to use dynamic pages (i.e., the URL contains a '?' character), be aware that not every search engine spider crawls dynamic pages as well as static pages. It helps to keep the parameters short and the number of them small.
如果你打算使用動(dòng)態(tài)頁(yè)面:鏈接中包含"?",必須了解:并非所有的搜索引擎的機(jī)器人能想對(duì)待靜態(tài)頁(yè)面一樣對(duì)待動(dòng)態(tài)頁(yè)面,保持動(dòng)態(tài)頁(yè)面的參數(shù)盡可能的少也會(huì) 很有幫助。
9.Keep the links on a given page to a reasonable number (fewer than 100).
讓一個(gè)頁(yè)面中的鏈接少于100個(gè)。
批注:用lynx -dump http://www.chedong.com/ 可以模擬從robot角度看到的頁(yè)面。其最后有鏈接統(tǒng)計(jì)
5. hibernate對(duì)動(dòng)態(tài)查詢的理解,如何應(yīng)用,并作應(yīng)用示例。
定義:
?靜態(tài)查詢:在編程時(shí)已經(jīng)確定要查詢的字段,這時(shí)編寫的HQL或QBC稱為靜態(tài)查詢。
?動(dòng)態(tài)查詢:在編程時(shí)無(wú)法確定要查詢的字段,這時(shí)編寫的HQL或QBC稱為動(dòng)態(tài)查詢。比如組合查詢時(shí),往往需要查詢的項(xiàng)很多,但不是每個(gè)項(xiàng)都必需。
(HQL適用于靜態(tài)查詢,QBC適用于動(dòng)態(tài)查詢)
以下分別用HQL和QBC實(shí)現(xiàn)動(dòng)態(tài)查詢:
1)下面的程序通過(guò)對(duì)字符串的拼裝使用HQL語(yǔ)句實(shí)現(xiàn)動(dòng)態(tài)查詢:
Public List findStu(String name, int age){
StringBuffer queryString= new StringBuffer();
Boolean conditionFound= false;
if(name!=null){
queryString.append(“lower(s.name) like :name”);
conditionFound= true;
}if(age!= 0){
if(conditionFound) queryString.append(“and”);
queryString.append(“s.age= :age”);
conditionFound=true;
}
String fromClause= conditionFound?”fromStudent s where” : ”fromStudent s”;
queryString.insert(0,fromClause).append(“order by s.name”);
Query query=getSession().createQuery(“queryString.toString()”);
if(name!=null)query.setString(“name”,’%’+name.toLowerCase()+’%’);
if(age!=0)query.setInteger(“age”,newInteger(age));
return query.list();
}
上面的代碼雖然可以正常工作,但是把簡(jiǎn)單的功能實(shí)現(xiàn)的相當(dāng)復(fù)雜,維護(hù)起來(lái)不方便。我們來(lái)看一下使用QBC查詢。
Public List findStu(String name, int age){
Criteria crit= getSession().createCriteria(Student.class);
if(name!=null){
crit.add(Restrictions.like(“name”,name,MatchMode.ANYWHERE));
}if(age!=0){
crit.add(Restrictions.eq(“age”,newInteger(age)));
}
crit.addOrder(Order.asc(“name”));
return crit.list();
}
6. Hibernate問(wèn)題
● a different object with the same identifier value was already associated with the session是什么原因?qū)е碌模?
在hibernate中同一個(gè)session里面有了兩個(gè)相同標(biāo)識(shí)但是是不同實(shí)體,當(dāng)這時(shí)運(yùn)行saveOrUpdate(object)操作的時(shí)候就會(huì)報(bào)這個(gè)錯(cuò)誤。種錯(cuò)誤經(jīng)常出現(xiàn)在一對(duì)多映射和多對(duì)多映射
在hibernate的開發(fā)中,HBM文件中會(huì)涉及到n2m的種種關(guān)系,但是,只有在出于必要性考慮的時(shí)候,才加上cascade="all" ,同時(shí),需小心規(guī)避由此引起的程序Exception.
考慮不周,會(huì)導(dǎo)致可能出現(xiàn)的最常見Exception是:
net.sf.hibernate.NonUniqueObjectException
a different object with the same identifier value was already associated with the session:......
解決辦法是:
1. 去掉引起Exception的associated Class對(duì)映HBM中的不必要cascade;
2. 檢查Exception發(fā)生位置的session的使用情況;
● Object references an unsaved transient instance-save the transient instance before flushing是什么原因?qū)е碌模?
某個(gè)對(duì)象的某個(gè)屬性是一個(gè)實(shí)體,在這個(gè)實(shí)體沒(méi)有保存之前就保存這個(gè)對(duì)象而造成了這個(gè)錯(cuò)誤。
以下舉個(gè)例子說(shuō)明以下
Session session = dao.getSession();
Transaction tx = session.beginTransaction();
Bo.setBman( form ,man,session);
Bo.saveChangeTable( man,session); // 把man當(dāng)作屬性賦給ChangeTable,并保存ChangeTable. 就是這出的錯(cuò),
dao.save(man,session); // 保存man
tx.commit();
==================== 應(yīng)該這樣寫:===============
Session session = dao.getSession();
Transaction tx = session.beginTransaction();
Bo.setBman( form ,man,session);
dao.save(man,session); // 保存man
Bo.saveChangeTable( man,session); // 把man當(dāng)作屬性賦給ChangeTable,并保存ChangeTable
tx.commit();
這樣,問(wèn)題就解決了。
● 如果修改一個(gè)列表中的一個(gè)數(shù)據(jù),會(huì)發(fā)現(xiàn)這個(gè)數(shù)據(jù)不穩(wěn)定,一會(huì)是修改后的,一會(huì)是修改前的,說(shuō)出其原因
因?yàn)閔ibernate利用了緩存技術(shù),sql適時(shí)提交,當(dāng)數(shù)據(jù)修改以后,數(shù)據(jù)并不一定及時(shí)提交到數(shù)據(jù)庫(kù),而是放在hibernate的緩存中,當(dāng)我們察看數(shù)據(jù)時(shí),可能是提交完的,也可能是沒(méi)有提交的,所以就會(huì)出現(xiàn)數(shù)據(jù)的臟讀。
如何避免使用緩存技術(shù)所帶來(lái)的臟數(shù)據(jù)問(wèn)題呢?
在設(shè)計(jì)、實(shí)現(xiàn)和測(cè)試時(shí),應(yīng)該清晰定義緩存數(shù)據(jù)的更新:
i. 不考慮緩存數(shù)據(jù)的更新,重啟軟件系統(tǒng)是一種必要的方式;
ii. 不考慮緩存數(shù)據(jù)的更新,緩存數(shù)據(jù)不可能成為臟數(shù)據(jù)(但在軟件系統(tǒng)中,往往“不可能”會(huì)在一次又一次的重構(gòu)之后變?yōu)?#8220;可能”);
iii. 考慮緩存數(shù)據(jù)的更新,當(dāng)源數(shù)據(jù)變化時(shí),實(shí)時(shí)更新緩存數(shù)據(jù)。
● 對(duì)于數(shù)據(jù)庫(kù)自增長(zhǎng)來(lái)說(shuō),在映射文件中主鍵配置,用哪種配置方案最好,最不容易出現(xiàn)問(wèn)題?
Hibernate標(biāo)識(shí)生成策略:
標(biāo)識(shí)符生成器 描述
increment 適用于代理主鍵。由Hibernate自動(dòng)以遞增方式生成。
identity 適用于代理主鍵。由底層數(shù)據(jù)庫(kù)生成標(biāo)識(shí)符。
sequence 適用于代理主鍵。Hibernate根據(jù)底層數(shù)據(jù)庫(kù)的序列生成標(biāo)識(shí)符,這要求底層數(shù)據(jù)庫(kù)支持序列。
hilo 適用于代理主鍵。Hibernate分局high/low算法生成標(biāo)識(shí)符。
seqhilo 適用于代理主鍵。使用一個(gè)高/低位算法來(lái)高效的生成long,short或者int類型的標(biāo)識(shí)符。
native適用于代理主鍵。根據(jù)底層數(shù)據(jù)庫(kù)對(duì)自動(dòng)生成標(biāo)識(shí)符的方式,自動(dòng)選擇identity、sequence或hilo。
uuid.hex 適用于代理主鍵。Hibernate采用128位的UUID算法生成標(biāo)識(shí)符。
uuid.string 適用于代理主鍵。UUID被編碼成一個(gè)16字符長(zhǎng)的字符串。
assigned 適用于自然主鍵。由Java應(yīng)用程序負(fù)責(zé)生成標(biāo)識(shí)符。
foreign 適用于代理主鍵。使用另外一個(gè)相關(guān)聯(lián)的對(duì)象的標(biāo)識(shí)符。
就這個(gè)問(wèn)題我認(rèn)為應(yīng)該用increment、native都可以
7. 概括你常用的框架的優(yōu)缺點(diǎn)。
1. Struts的優(yōu)缺點(diǎn):
具體來(lái)講,Struts的優(yōu)點(diǎn)有:
1. 實(shí)現(xiàn)MVC模式,結(jié)構(gòu)清晰,使開發(fā)者只關(guān)注業(yè)務(wù)邏輯的實(shí)現(xiàn).
2. 有豐富的tag可以用 ,Struts的標(biāo)記庫(kù)(Taglib),如能靈活動(dòng)用,則能大大提高開發(fā)效率。另外,就目前國(guó)內(nèi)的JSP開發(fā)者而言,除了使用JSP自帶的常用標(biāo)記外,很少開發(fā)自己的標(biāo)記,或許Struts是一個(gè)很好的起點(diǎn)。
3. 頁(yè)面導(dǎo)航.頁(yè)面導(dǎo)航將是今后的一個(gè)發(fā)展方向,事實(shí)上,這樣做,使系統(tǒng)的脈絡(luò)更加清晰。通過(guò)一個(gè)配置文件,即可把握整個(gè)系統(tǒng)各部分之間的聯(lián)系,這對(duì)于后期的維護(hù)有著莫大的好處。尤其是當(dāng)另一批開發(fā)者接手這個(gè)項(xiàng)目時(shí),這種優(yōu)勢(shì)體現(xiàn)得更加明顯。
4. 提供Exception處理機(jī)制 .
5. 數(shù)據(jù)庫(kù)鏈接池管理
6. 支持I18N
缺點(diǎn):
一、 轉(zhuǎn)到展示層時(shí),需要配置forward,每一次轉(zhuǎn)到展示層,相信大多數(shù)都是直接轉(zhuǎn)到j(luò)sp,而涉及到轉(zhuǎn)向,需要配置forward,如果有十個(gè)展示層的jsp,需要配置十次struts,而且還不包括有時(shí)候目錄、文件變更,需要重新修改forward,注意,每次修改配置之后,要求重新部署整個(gè)項(xiàng)目,而tomcate這樣的服務(wù)器,還必須重新啟動(dòng)服務(wù)器,如果業(yè)務(wù)變更復(fù)雜頻繁的系統(tǒng),這樣的操作簡(jiǎn)單不可想象。現(xiàn)在就是這樣,幾十上百個(gè)人同時(shí)在線使用我們的系統(tǒng),大家可以想象一下,我的煩惱有多大。
二、 Struts 的Action必需是thread-safe方式,它僅僅允許一個(gè)實(shí)例去處理所有的請(qǐng)求。所以action用到的所有的資源都必需統(tǒng)一同步,這個(gè)就引起了線程安全的問(wèn)題。
三、 測(cè)試不方便. Struts的每個(gè)Action都同Web層耦合在一起,這樣它的測(cè)試依賴于Web容器,單元測(cè)試也很難實(shí)現(xiàn)。不過(guò)有一個(gè)Junit的擴(kuò)展工具Struts TestCase可以實(shí)現(xiàn)它的單元測(cè)試。
四、 類型的轉(zhuǎn)換. Struts的FormBean把所有的數(shù)據(jù)都作為String類型,它可以使用工具Commons-Beanutils進(jìn)行類型轉(zhuǎn)化。但它的轉(zhuǎn)化都是在Class級(jí)別,而且轉(zhuǎn)化的類型是不可配置的。類型轉(zhuǎn)化時(shí)的錯(cuò)誤信息返回給用戶也是非常困難的。
五、 對(duì)Servlet的依賴性過(guò)強(qiáng). Struts處理Action時(shí)必需要依賴ServletRequest 和ServletResponse,所有它擺脫不了Servlet容器。
六、 前端表達(dá)式語(yǔ)言方面.Struts集成了JSTL,所以它主要使用JSTL的表達(dá)式語(yǔ)言來(lái)獲取數(shù)據(jù)。可是JSTL的表達(dá)式語(yǔ)言在Collection和索引屬性方面處理顯得很弱。
七、 對(duì)Action執(zhí)行的控制困難. Struts創(chuàng)建一個(gè)Action,如果想控制它的執(zhí)行順序?qū)?huì)非常困難。甚至你要重新去寫Servlet來(lái)實(shí)現(xiàn)你的這個(gè)功能需求。
八、 對(duì)Action 執(zhí)行前和后的處理. Struts處理Action的時(shí)候是基于class的hierarchies,很難在action處理前和后進(jìn)行操作。
九、 對(duì)事件支持不夠. 在struts中,實(shí)際是一個(gè)表單Form對(duì)應(yīng)一個(gè)Action類(或DispatchAction),換一句話說(shuō):在Struts中實(shí)際是一個(gè)表單只能對(duì)應(yīng)一個(gè)事件,struts這種事件方式稱為application event,application event和component event相比是一種粗粒度的事件。
Struts重要的表單對(duì)象ActionForm是一種對(duì)象,它代表了一種應(yīng)用,這個(gè)對(duì)象中至少包含幾個(gè)字段,這些字段是Jsp頁(yè)面表單中的input字段,因?yàn)橐粋€(gè)表單對(duì)應(yīng)一個(gè)事件,所以,當(dāng)我們需要將事件粒度細(xì)化到表單中這些字段時(shí),也就是說(shuō),一個(gè)字段對(duì)應(yīng)一個(gè)事件時(shí),單純使用Struts就不太可能,當(dāng)然通過(guò)結(jié)合JavaScript也是可以轉(zhuǎn)彎實(shí)現(xiàn)的。
2.Hibernate的優(yōu)缺點(diǎn):
Hibernate是一個(gè)開放源代碼的對(duì)象關(guān)系映射框架,它對(duì)JDBC進(jìn)行了非常輕量級(jí)的對(duì)象封裝,使得Java程序員可以隨心所欲的使用對(duì)象編程思維來(lái)操縱數(shù)據(jù)庫(kù)。
Hibernate可以應(yīng)用在任何使用JDBC的場(chǎng)合,既可以在Java的客戶端程序?qū)嵱茫部梢栽赟ervlet/JSP的Web應(yīng)用中使用,最具革命意義的是,Hibernate可以在應(yīng)用EJB的J2EE架構(gòu)中取代CMP,完成數(shù)據(jù)持久化的重任。
大多數(shù)開發(fā)機(jī)構(gòu)經(jīng)常采取創(chuàng)建各自獨(dú)立的數(shù)據(jù)持久層。一旦底層的數(shù)據(jù)結(jié)構(gòu)發(fā)生改變,那么修改應(yīng)用的其余部分使之適應(yīng)這種改變的代價(jià)將是十分巨大的。Hibernate適時(shí)的填補(bǔ)了這一空白,它為Java應(yīng)用提供了一個(gè)易用的、高效率的對(duì)象關(guān)系映射框架。hibernate是個(gè)輕量級(jí)的持久性框架,功能卻非常豐富。
優(yōu)點(diǎn):
a. Hibernate 使用 Java 反射機(jī)制而不是字節(jié)碼增強(qiáng)程序來(lái)實(shí)現(xiàn)透明性。
b. Hibernate 的性能非常好,因?yàn)樗莻€(gè)輕量級(jí)框架。映射的靈活性很出色。
c. 它支持各種關(guān)系數(shù)據(jù)庫(kù),從一對(duì)一到多對(duì)多的各種復(fù)雜關(guān)系。
缺點(diǎn):它限制您所使用的對(duì)象模型。(例如,一個(gè)持久性類不能映射到多個(gè)表)其獨(dú)有的界面和可憐的市場(chǎng)份額也讓人不安,盡管如此,Hibernate 還是以其強(qiáng)大的發(fā)展動(dòng)力減輕了這些風(fēng)險(xiǎn)。其他的開源持久性框架也有一些,不過(guò)都沒(méi)有 Hibernate 這樣有市場(chǎng)沖擊力。
3. Spring框架的優(yōu)缺點(diǎn)
它是一個(gè)開源的項(xiàng)目,而且目前非常活躍;它基于IoC(Inversion of Control,反向控制)和AOP的構(gòu)架多層j2ee系統(tǒng)的框架,但它不強(qiáng)迫你必須在每一層中必須使用Spring,因?yàn)樗K化的很好,允許你根據(jù)自己的需要選擇使用它的某一個(gè)模塊;它實(shí)現(xiàn)了很優(yōu)雅的MVC,對(duì)不同的數(shù)據(jù)訪問(wèn)技術(shù)提供了統(tǒng)一的接口,采用IoC使得可以很容易的實(shí)現(xiàn)bean的裝配,提供了簡(jiǎn)潔的AOP并據(jù)此實(shí)現(xiàn)Transcation Managment,等等
優(yōu)點(diǎn)
a. Spring能有效地組織你的中間層對(duì)象,不管你是否選擇使用了EJB。如果你僅僅使用了Struts或其他為J2EE的 API特制的framework,Spring致力于解決剩下的問(wèn)題。
b. Spring能消除在許多工程中常見的對(duì)Singleton的過(guò)多使用。根據(jù)我的經(jīng)驗(yàn),這是一個(gè)很大的問(wèn)題,它降低了系統(tǒng)的可測(cè)試性和面向?qū)ο蟮某潭取?
c. 通過(guò)一種在不同應(yīng)用程序和項(xiàng)目間一致的方法來(lái)處理配置文件,Spring能消除各種各樣自定義格式的屬性文件的需要。曾經(jīng)對(duì)某個(gè)類要尋找的是哪個(gè)魔法般的屬性項(xiàng)或系統(tǒng)屬性感到不解,為此不得不去讀Javadoc甚至源編碼?有了Spring,你僅僅需要看看類的JavaBean屬性。Inversion of Control的使用(在下面討論)幫助完成了這種簡(jiǎn)化。
d. 通過(guò)把對(duì)接口編程而不是對(duì)類編程的代價(jià)幾乎減少到?jīng)]有,Spring能夠促進(jìn)養(yǎng)成好的編程習(xí)慣。
e. Spring被設(shè)計(jì)為讓使用它創(chuàng)建的應(yīng)用盡可能少的依賴于他的APIs。在Spring應(yīng)用中的大多數(shù)業(yè)務(wù)對(duì)象沒(méi)有依賴于Spring。
f. 使用Spring構(gòu)建的應(yīng)用程序易于單元測(cè)試。
g. Spring能使EJB的使用成為一個(gè)實(shí)現(xiàn)選擇,而不是應(yīng)用架構(gòu)的必然選擇。你能選擇用POJOs或local EJBs來(lái)實(shí)現(xiàn)業(yè)務(wù)接口,卻不會(huì)影響調(diào)用代碼。
h. Spring幫助你解決許多問(wèn)題而無(wú)需使用EJB。Spring能提供一種EJB的替換物,它們適用于許多web應(yīng)用。例如,Spring能使用AOP提供聲明性事務(wù)管理而不通過(guò)EJB容器,如果你僅僅需要與單個(gè)數(shù)據(jù)庫(kù)打交道,甚至不需要一個(gè)JTA實(shí)現(xiàn)。
i. Spring為數(shù)據(jù)存取提供了一個(gè)一致的框架,不論是使用的是JDBC還是O/R mapping產(chǎn)品
Spring確實(shí)使你能通過(guò)最簡(jiǎn)單可行的解決辦法來(lái)解決你的問(wèn)題。而這是有有很大價(jià)值的。
缺點(diǎn):使用人數(shù)不多、jsp中要寫很多代碼、控制器過(guò)于靈活,缺少一個(gè)公用控制器
8. 是否了解設(shè)計(jì)模式,將幾種常用的設(shè)計(jì)模式的思想、并舉例。
創(chuàng)建模式:
Factory、Prototype(原型)、Builder、Singleton
結(jié)構(gòu)模式:
Facade(外觀)、Proxy(代理)、Adapter(適配器)、Composite(組合)、Decorator(油漆工)、Bridge、Flyweight(享元)
行為模式:
Template、Memento(備忘機(jī)制)、Observer、Chain of Responsibility(職責(zé)鏈)、Command、State、Strategy(策略)、Mediator(中介者)、Interdivter(解釋器)、Visitor
9. 頁(yè)面重復(fù)刷新,如何解決?客戶的行為是無(wú)法控制的,那如何控制客戶的重復(fù)刷新導(dǎo)致的重復(fù)提交。
Jsp防止頁(yè)面刷新表單自提交重復(fù)提交思路:
1. 提交后禁用提交按鈕(大部分人都是這樣做的)
2. 用javascript實(shí)現(xiàn)
10. 如何精確記錄同時(shí)在線人數(shù)
我們可以利用Servlet規(guī)范中定義的事件監(jiān)聽器(Listener)來(lái)解決這個(gè)問(wèn)題,實(shí)現(xiàn)更準(zhǔn)確的在線人數(shù)統(tǒng)計(jì)功能。對(duì)每一個(gè)正在訪問(wèn)的用戶,J2EE應(yīng)用服務(wù)器會(huì)為其建立一個(gè)對(duì)應(yīng)的HttpSession對(duì)象。當(dāng)一個(gè)瀏覽器第一次訪問(wèn)網(wǎng)站的時(shí)候,J2EE應(yīng)用服務(wù)器會(huì)新建一個(gè)HttpSession對(duì)象,并觸發(fā)HttpSession創(chuàng)建事件,如果注冊(cè)了HttpSessionListener事件監(jiān)聽器,則會(huì)調(diào)用HttpSessionListener事件監(jiān)聽器的sessionCreated方法。相反,當(dāng)這個(gè)瀏覽器訪問(wèn)結(jié)束超時(shí)的時(shí)候,J2EE應(yīng)用服務(wù)器會(huì)銷毀相應(yīng)的HttpSession對(duì)象,觸發(fā)HttpSession銷毀事件,同時(shí)調(diào)用所注冊(cè)HttpSessionListener事件監(jiān)聽器的sessionDestroyed方法。
可見,對(duì)應(yīng)于一個(gè)用戶訪問(wèn)的開始和結(jié)束,相應(yīng)的有sessionCreated方法和sessionDestroyed方法執(zhí)行。這樣,我們只需要在HttpSessionListener實(shí)現(xiàn)類的sessionCreated方法中讓計(jì)數(shù)器加1,在sessionDestroyed方法中讓計(jì)數(shù)器減1,就輕松實(shí)現(xiàn)了網(wǎng)站在線人數(shù)的統(tǒng)計(jì)功能。
下面就是利用HttpSessionListener實(shí)現(xiàn)在線人數(shù)統(tǒng)計(jì)的一個(gè)例子,這個(gè)例子已經(jīng)在中創(chuàng)軟件的J2EE應(yīng)用服務(wù)器InforWeb中測(cè)試通過(guò)。
首先,編寫一個(gè)簡(jiǎn)單的計(jì)數(shù)器,代碼如下:
package gongfei.cmc.articles.onlinecounter;
public class OnlineCounter {
private static long online = 0;
public static long getOnline() {
return online;
}
public static void raise(){
online++;
}
public static void reduce(){
online--;
}
}
然后,編寫HttpSessionListener實(shí)現(xiàn)類,在這個(gè)實(shí)現(xiàn)類的sessionCreated方法中調(diào)用OnlineCounter的raise方法,在sessionDestroyed方法中調(diào)用OnlineCounter的reduce方法,代碼如下:
package gongfei.cmc.articles.onlinecounter;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class OnlineCounterListener implements HttpSessionListener {
public void sessionCreated(HttpSessionEvent hse) {
OnlineCounter.raise();
}
public void sessionDestroyed(HttpSessionEvent hse) {
OnlineCounter.reduce();
}
}
再然后,把這個(gè)HttpSessionListener實(shí)現(xiàn)類注冊(cè)到網(wǎng)站應(yīng)用中,也就是在網(wǎng)站應(yīng)用的web.xml中加入如下內(nèi)容:
<web-app>
……
<listener>
<listener-class>
gongfei.cmc.articles.example.OnlineCounterListener
</listener-class>
</listener>
……
</web-app>
OK,在線人數(shù)統(tǒng)計(jì)功能已經(jīng)實(shí)現(xiàn),只要在JSP頁(yè)面中加入下面這樣的腳本就能顯示但前在線人數(shù)了:
<%@ page language="java" pageEncoding="GB2312" %>
<%@ page language="java" pageEncoding="GB2312" %>
<%@ page import="gongfei.cmc.articles.onlinecounter.OnlineCounter" %>
<html>
<head><title>On Line Counert</title></head>
<body bgcolor="#FFFFFF">
On line:<%=OnlineCounter.getOnline()%>
</body>
</html>
11. 亂碼解決方案。是否遇到過(guò)?有哪些?講解具體遇到的情形,并說(shuō)出你在具體的應(yīng)用中的解決方案。
1.JSP輸出中文的亂碼問(wèn)題
所謂在jsp輸出中文,即直接在jsp中輸出中文,或者給變量賦中文值再輸出等,這種情況下的亂碼問(wèn)題往往是因?yàn)闆](méi)有給jsp頁(yè)面制定顯示中文字符的編碼方式,解決辦法如下:
1)在jsp頁(yè)面頭部加上語(yǔ)句<%@ page contentType="text/html;charset=utf-8"%>(在Servlet中使用httpServletResponse.setContentType("text/html;charset=utf-8"),最好同時(shí)在jsp頁(yè)面的head部分加上<meta http-equiv="Content-Type" content="text/html;charset="utf-8">
2)在每次要輸出中文的地方主動(dòng)轉(zhuǎn)換編碼方式,比如要在頁(yè)面中輸入“中文”二字,就可以用以下的方法:
<%
String str="中文";
byte[] tmpbyte=str.getBytes("ISO8859_1");
str=new String(tmpbyte);
out.println(str);
%>
對(duì)于以上這兩種方法,顯然第一種方法更通用一點(diǎn),只需要在一個(gè)頁(yè)面中添加一次代碼即可;而對(duì)于第二種方法,在每個(gè)需要輸出中文的地方都需要轉(zhuǎn)碼,如果這樣的地方很多,這將是一個(gè)繁重的工作。
2.獲取表單提交的數(shù)據(jù)時(shí)的中文亂碼問(wèn)題
在沒(méi)有加任何其他處理之前,用request.getParameter("paramName")獲取表單提交中的數(shù)據(jù),且表單數(shù)據(jù)中含有中文時(shí),返回的字符串會(huì)呈現(xiàn)亂碼。出現(xiàn)這種問(wèn)題的原因是Tomcat的j2ee實(shí)現(xiàn)對(duì)表單提交,即以POST方式提交的參數(shù)采用默認(rèn)的ISO-8859-1來(lái)處理。
解決此問(wèn)題的辦法有兩個(gè):
1)不修改其他配置,只是在將表單中的中文數(shù)據(jù)區(qū)出來(lái)后再轉(zhuǎn)換編碼,方法如語(yǔ)句 String str=request.getParameter("chStr");String str = new String(str.getBytes("ISO-8859-1"),"UTF-8");但這種方法只是從一個(gè)局部來(lái)考慮問(wèn)題,如果這樣的情況很多,就要寫很多次,勢(shì)必加大工作量。
2)讓對(duì)所有頁(yè)面的請(qǐng)求都通過(guò)一個(gè)Filter,將處理字符集設(shè)置為utf-8(根據(jù)自己需要也可以設(shè)置成其他的,如gb2312,gbk)。具體做法參考Tomcat的webapps/servlet-exemples目錄有一個(gè)完整的例子,也可以參考其中web.xml和SetCharacterEncodingFilter的配置.
3.URL中的中文問(wèn)題
對(duì)于直接通過(guò)在url中傳遞中文參數(shù),如http://localhost:8080/a.jsp?str="中文"這樣的get請(qǐng)求,在服務(wù)器端用request.getParameter("name")時(shí)返回的往往是亂碼。按照以上的做法設(shè)置Filter沒(méi)有用,用request.setCharacterEncoding("utf-8")的方式,仍然不管用。造成這種結(jié)果的原因是Tomcat中以get方式提交的請(qǐng)求對(duì)query-string處理時(shí)采用了和post方法不一樣的處理方式。
解決這個(gè)問(wèn)題的方法是是打開Tomcat安裝目錄下的/conf/server.xml文件,找到Connector塊,往其中添加URLEncoding="utf-8"/>
4.數(shù)據(jù)庫(kù)訪問(wèn)時(shí)的亂碼問(wèn)題
數(shù)據(jù)庫(kù)中所有表的編碼方式和jsp中的使用的編碼要保持一致,這樣做的目的可以減少不必要的編碼轉(zhuǎn)換問(wèn)題.另外,在使用jdbc連接MySQL數(shù)據(jù)庫(kù)時(shí),連接字符串寫成如下形式可以避免一些中文問(wèn)題:
jdbc://mysql://hostname:port/DBname?user=username&password=pwd&useUnicode=true&character Encoding=utf-8
如果是以數(shù)據(jù)源的方式連接數(shù)據(jù)庫(kù),配置文件中使用:
<parameter>
<name>url</name>
<value>jdbc:mysql://hostname:port/DBname?&useUnicode=true&characterEncoding=utf-8
</value>
</parameter>
但是如果使用一個(gè)已經(jīng)存在的數(shù)據(jù)庫(kù),數(shù)據(jù)庫(kù)的編碼方式為ISO-8859-1,而Web應(yīng)用中使用的utf-8,且數(shù)據(jù)庫(kù)已經(jīng)有很多重要的信息,因此不能通過(guò)更改數(shù)據(jù)庫(kù)的編碼方式來(lái)解決。這個(gè)時(shí)候,在往數(shù)據(jù)庫(kù)中寫數(shù)據(jù)時(shí),一定要在jdbc連接字符串中加入“useUnicode=true&characterEncoding=ISO-8859-1”,這樣可以順利的王數(shù)據(jù)庫(kù)寫入正常的數(shù)據(jù)。但是,在將數(shù)據(jù)讀出數(shù)據(jù)庫(kù)時(shí),亂碼又會(huì)出現(xiàn),這個(gè)時(shí)候就應(yīng)該在數(shù)據(jù)取出時(shí)對(duì)其轉(zhuǎn)碼,可以將轉(zhuǎn)碼功能寫為一個(gè)函數(shù),具體實(shí)現(xiàn)如下:
public String charConvert(String src){
String result=null;
if(src!=null){
try{
result=new String(src.getBytes("ISO-8859-1"),"UTF-8");
}catch(Exception e){
result=null;
}
}
return result;
}
于是,在數(shù)據(jù)庫(kù)讀出數(shù)據(jù)過(guò)后調(diào)用charConvert(rs.getString("colName"));這樣就可以正常的顯示數(shù)據(jù)庫(kù)中的中文數(shù)據(jù)了。