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

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

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

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

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

public void foo() {

Connection conn=

getConnection();

Statement stmt = null;

try {

conn=getConnection();

stmt=conn.createStatement();

} catch(Exception e) {

} finally {

close(stmt, conn);

}

}

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

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

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

任意申請數(shù)據(jù)庫連接

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

public class Customer {

/更新序列號使其加1/

public void sequencePlus(){

Connection conn=null;

Statement stmt =null;

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

}

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

public int getSequenceCurrentVal(){

Connection conn=null;

Statement stmt=null;

ResultSet rset =null;

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

}

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

public void addCustomer(String name) {

Connection conn=null;

PreparedStatement stmt = null;

ResultSet rset=null;

sequencePlus();// 序列號加1;

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

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

}

}

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

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

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

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

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

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