如何處理幾種常見的數(shù)據(jù)庫(kù)不當(dāng)連接
來(lái)源:易賢網(wǎng) 閱讀:1072 次 日期:2015-09-04 20:32:41
溫馨提示:易賢網(wǎng)小編為您整理了“如何處理幾種常見的數(shù)據(jù)庫(kù)不當(dāng)連接”,方便廣大網(wǎng)友查閱!

基于J2EE平臺(tái)的應(yīng)用開發(fā)中,大多數(shù)的應(yīng)用都需要跟數(shù)據(jù)庫(kù)打交道。而自從接觸JDBC起,我們便不止一次地被告之:數(shù)據(jù)庫(kù)資源是十分寶貴的系統(tǒng)資源,一定要謹(jǐn)慎使用。但令人遺憾的是,在筆者見過(guò)的大部分跟數(shù)據(jù)庫(kù)相關(guān)的應(yīng)用開發(fā)中,針對(duì)數(shù)據(jù)庫(kù)資源的使用總是充斥著這樣或者那樣的問(wèn)題。在本文中,筆者對(duì)一些常見的錯(cuò)誤或者不當(dāng)?shù)氖褂脭?shù)據(jù)庫(kù)資源的案例進(jìn)行介紹與分析,幫助讀者避免某些錯(cuò)誤的發(fā)生。

未正確關(guān)閉數(shù)據(jù)庫(kù)連接

自增長(zhǎng)整數(shù)型字段賦值表

申請(qǐng)了數(shù)據(jù)庫(kù)連接,卻沒有及時(shí)關(guān)閉,這是最常見的數(shù)據(jù)庫(kù)連接使用方面的錯(cuò)誤。犯這種錯(cuò)誤的原因很多,以下是常見的一種比較低級(jí)的錯(cuò)誤:

public void foo() {

Connection conn=

getConnection();

Statement stmt = null;

try {

conn=getConnection();

stmt=conn.createStatement();

} catch(Exception e) {

} finally {

close(stmt, conn);

}

}

在上述案例中的第2行代碼中,作者申請(qǐng)了一個(gè)Connection,但在第6行代碼中,又申請(qǐng)了一個(gè)新的,并且丟失了第一次申請(qǐng)的Connection的引用。至此,當(dāng)程序每調(diào)一次Foo方法,將導(dǎo)致申請(qǐng)一個(gè)新的Connection而沒有釋放它。因此,當(dāng)數(shù)據(jù)庫(kù)達(dá)到最大連接數(shù)時(shí),將導(dǎo)致整個(gè)應(yīng)用的運(yùn)行失敗。

避免這種錯(cuò)誤的方法有很多,譬如,可采用類似于FindBugs的代碼分析工具對(duì)應(yīng)用的源碼進(jìn)行分析,找出可能產(chǎn)生錯(cuò)誤的代碼。

此外,在應(yīng)用中,我們要頻繁地對(duì)申請(qǐng)的數(shù)據(jù)庫(kù)連接進(jìn)行關(guān)閉與釋放。此時(shí),建議封裝成某些工具類使用,并且要盡可能安全地關(guān)閉數(shù)據(jù)庫(kù)連接。

任意申請(qǐng)數(shù)據(jù)庫(kù)連接

不考慮事務(wù)上下文,任意申請(qǐng)數(shù)據(jù)庫(kù)連接資源也是常見的不當(dāng)用法。但這種問(wèn)題往往是難以克服的,根源在于Java是一種面向?qū)ο蟮恼Z(yǔ)言,而數(shù)據(jù)庫(kù)的事務(wù)卻是一種批量化的操作過(guò)程。我們以常見的序列號(hào)的實(shí)現(xiàn)方案為例:在某些應(yīng)用場(chǎng)景中,我們需要一種自增長(zhǎng)的整數(shù)型字段。但由于不同的數(shù)據(jù)庫(kù)有不同的實(shí)現(xiàn),所以,為達(dá)到各個(gè)數(shù)據(jù)庫(kù)兼容的目的,我們常用的解決方案是,新建一張T_SEQUENCE表,它可能包含的字段有:NAME varchar(100), CURRENT_VAL number(10);其中,NAME存放序列的名稱,而CURRENT_VAL存放序列的當(dāng)前值。假設(shè)某一業(yè)務(wù)對(duì)象Customer需要新增一筆記錄時(shí),為獲得不重復(fù)且自增長(zhǎng)的Customer ID,需要將T_SEQUENCE表中與該業(yè)務(wù)表對(duì)應(yīng)的序列號(hào)加1并更新,然后將更新后的值作為Customer的ID。我們以面向?qū)ο蟮?種方法來(lái)實(shí)現(xiàn):

public class Customer {

/更新序列號(hào)使其加1/

public void sequencePlus(){

Connection conn=null;

Statement stmt =null;

……//將T_SEQUENCE的序列號(hào)當(dāng)前值加1;

}

/獲取當(dāng)前序列號(hào)/

public int getSequenceCurrentVal(){

Connection conn=null;

Statement stmt=null;

ResultSet rset =null;

……// 獲取當(dāng)前的序列號(hào)值;

}

/新增一條Customer記錄,自動(dòng)根據(jù)序列號(hào)生成主鍵/

public void addCustomer(String name) {

Connection conn=null;

PreparedStatement stmt = null;

ResultSet rset=null;

sequencePlus();// 序列號(hào)加1;

int id = getSequenceCurrentVal(); // 得到當(dāng)前序列號(hào);

…….// 將最新序列號(hào)作為新的T_Customer記錄的主鍵插入;

}

}

針對(duì)這種應(yīng)用場(chǎng)景,我們首先需要認(rèn)識(shí)到:上述3個(gè)方法應(yīng)該屬于同一個(gè)數(shù)據(jù)庫(kù)事務(wù)。否則,在并發(fā)情況下,將出現(xiàn)由于主鍵重復(fù)而導(dǎo)致數(shù)據(jù)插入失敗的情況。但同時(shí),我們也需要看到:即便上述3個(gè)方法的執(zhí)行位于同一個(gè)事務(wù)中,但3個(gè)方法使用的是不同的數(shù)據(jù)庫(kù)連接,雖然在sequencePlus方法中將T_SEQUENCE表中的數(shù)據(jù)加1 ,但在事務(wù)并未提交的情況下,由于Connection隔離級(jí)別的原因,在getSequenceCurrentVal方法中,是看不到sequencePlus方法中更新以后的數(shù)據(jù)的。這樣,也將導(dǎo)致數(shù)據(jù)插入失敗,因?yàn)橹麈I勢(shì)必跟舊有ID值重復(fù)。

因此,傳統(tǒng)編程方法為克服上述問(wèn)題,只有在上述的方法中使用同一個(gè)Connection,才能夠保證業(yè)務(wù)數(shù)據(jù)的正確。

更多信息請(qǐng)查看IT技術(shù)專欄

更多信息請(qǐng)查看數(shù)據(jù)庫(kù)
易賢網(wǎng)手機(jī)網(wǎng)站地址:如何處理幾種常見的數(shù)據(jù)庫(kù)不當(dāng)連接
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請(qǐng)考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!

2025國(guó)考·省考課程試聽報(bào)名

  • 報(bào)班類型
  • 姓名
  • 手機(jī)號(hào)
  • 驗(yàn)證碼
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡(jiǎn)要咨詢 | 簡(jiǎn)要咨詢須知 | 加入群交流 | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號(hào):滇ICP備2023014141號(hào)-1 云南省教育廳備案號(hào):云教ICP備0901021 滇公網(wǎng)安備53010202001879號(hào) 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號(hào)
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65099533/13759567129 獲取招聘考試信息及咨詢關(guān)注公眾號(hào):hfpxwx
咨詢QQ:526150442(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報(bào)警專用圖標(biāo)