2012-04-20 18 views
1

我有一個主控制器servlet,其中我實例化數據源。 servlet打開和關閉連接。主要是,servlet使用「工廠模式」從應用程序實例化命令。這裏是一些代碼來解釋:來自jndi數據源/連接池的jdbc連接的「惰性初始化」:可行性

public void init() throws ServletException { 
    super.init(); 
    try { 
      datasource =(DataSource) getServletContext().getAttribute("DBCPool"); 
    } 
    catch (Exception e) { 

    } 
} 
protected void processRequest(HttpServletRequest request, HttpServletResponse response) 
throws ServletException, IOException { 
    //some code... 
    Connection connection = null; 
    if(cmd.mightNeedLazyLoadingAConnection) 
    { 

     connection = null; 
    } 
    else 
     connection = getConnection();//where getConnection is a method: datasource.getconnection(); 

     //now a command (a java class) is instantied, to which the "null" CONNECTION obj is passed as parameter 
    cmdFactory.getInstance().getCommand(Cmd).execute(tsk,connection); 


    //some code 

//Then wherever there is catch exception i close() the connection 
// and it is always closed in finally 
finally { 
if(connection!=null) 
    connection.close() 
} 

} 

現在,這款擁有問題對於第一種情況,即連接= NULL,因爲它從來沒有關閉在「終於」部分連接(解釋了爲什麼在更新下面)。

「連接= NULL」對於其中命令可能需要打開,因爲它正在尋求在identity map緩存中的數據數據庫連接的情況。

我試圖通過「連接」 OBJ作爲.execute一個 「空」 參數(TSK,連接);,然後在相應的Java類打開連接如果需要

- >它確實打開命令內部的連接,然而,當處理返回到的servlet:「連接」是null作爲因而不關閉。
我能做些什麼來使「連接」 obj的值得到更新,以便當返回到servlet時它不再是「空」,我可以關閉它?

我通常喜歡使用打開/關閉分貝連接的控制器servlet,所以這將是應對這種情況的,你必須做一些「懶加載」一個數據庫連接的最佳方式從池中同時保持打開/關閉的db連接分配給servlet?

更新(解釋進一步):

  • 說,我有一個命令:X.java
  • 該命令可能/可能不會需要一個數據庫連接(取決於如果數據搜索是否在身份地圖或不)

我想要的系統是:

(1)「客戶請求」

(2)--->「的Servlet」: command.execute(連接)//其中連接= NULL現在

( 3)--->「命令X」:我需要去數據庫或記錄是在身份地圖嗎?
(3。一)在需要的地方去數據庫案例:
(3.A.1)連接=的DataSource.getConnection
(3.A.2)去獲取數據

(4) - - >與Servlet:接近「的Servlet」

眼下的「連接」這是工作,直到(3.A.2),但一旦回到(4)看來,連接仍然是「空「,因此代碼:

finally { 
if(connection!=null) 
    connection.close() 
} 

不起作用(不關閉連接),因此數據庫池就這樣被排空。 連接 - 如何從「null」開始,在命令「X」內更改 - 將「globaly」更新爲其新值,而不僅僅是命令範圍「X」中的「更新」?

SOLUTION(S)

在您遇到相同的情況下,您可以選擇這些2的解決方案:

  • 您可以使用LazyConnectionDataSourceProxy,由作爲mentionned @Ryan Stewart爲「乾淨的抽象」和更專業的解決方案

  • 或者,如果你想使用下面介紹我的解決方案(基本上我實現類似於類「LazyConnectionDataSourceProxy」,但它並不像乾淨的,它具有比「LazyConnectionDataSourceProxy」細節較少抽象)

我個人解決方案,詳細說明:

  • 我創建了一個「助手」類,它的構造採用了「數據源」作爲參數
  • 這個輔助類有以下方法:「懶惰得到」從池連接「的CLOS e「連接
  • 該類在servlet中實例化,並且在整個應用程序中需要連接池只有需要

這是我添加的代碼/在servlet修改:

Connection connection = null; 
if(cmd.mightNeedLazyLoadingAConnection) 
{ 

    helper hp = new helper(datasource); 
    cmdFactory.getInstance().getCommand(Cmd).execute(tsk,hp); 
} 
else 
{ 
    connection = getConnection(); 
    cmdFactory.getInstance().getCommand(Cmd).execute(tsk,connection); 
} 

然後,在命令 「X」 表示,需要一個分貝連接我做:

Connection connection = hp.LazyGet();//Now got a connection from the pool 

而這樣,當進程流程回到servlet級別時,我可以:

  • 關閉
  • rollback
  • commit
  • etc ..

所有關於helper類的hp對象。

做我從這個有什麼好處:

  • 我限制所有數據庫開啓/關閉/提交/回滾一個的地方,也就是Servlet,這是負責執行命令。
  • 有案件:永遠不需要DB /總是需要DB /可能需要DB因此現在我通過1/3減少調用數據庫,這是相當多的知道數據庫調用與新的指數增長功能和新用戶註冊。

這可能不是最清潔解決辦法,但這種方式有一個額外的「不必要」的1/3數據庫調用之間,那肯定是更好。或者如果你想測試,抽象和乾淨的方法只是使用LazyConnectionDataSourceProxy

回答

1

使用LazyConnectionDataSourceProxy。然後,每次只需獲得一個「連接」,但只有在實際需要時纔會打開真正的連接。因此,您遵守Hiro2k指出的「創建/銷燬」智慧,因爲連接的生命週期完全由您的servlet管理。

+0

感謝您的提示。我剛剛在幾分鐘前發佈了我的解決方案。我沒有使用框架,但我做了某種助手/代理類(檢查我的答案)。 – shadesco 2012-04-20 22:45:57

+0

我沒有說使用框架。 'LazyConnectionDataSourceProxy'的功能與您的解決方案所描述的幾乎完全相同,只不過它隱藏了乾淨的抽象層後面的髒東西。沒有「可能需要連接」或「懶得到」的概念。你只是把它看作是一個普通的'DataSource',它提供了正常的'Connection's,你可以免費獲得懶惰。出於這些原因,這是一個相當好的選擇。 – 2012-04-21 00:06:04

+0

我明白了..我會重新檢查一下並瞭解更多信息 – shadesco 2012-04-21 02:25:37

0

在您的具體情況下,唯一的方法就是返回連接。 Java沒有任何可以幫助你的引用語義傳遞,與C不同的是,你可以將引用傳遞給連接,然後在方法中設置它。

我不建議你的方法返回的連接,而不是記住這個簡單的規則,一切都將按照您期望:

創建它,是負責銷燬它的對象。

如果你想要做的不是爲不需要的命令實例化一個連接,那麼在你的命令接口中添加一個方法,只需要返回一個方法。

Command command = cmdFactory.getInstance().getCommand(Cmd); 
if(command.requiresConnections){ 
    connection = getConnection(); 
} 
command.execute(tsk,connection); 
+0

thx的提示。我無法返回連接,因爲每個命令都會返回數據發送到客戶端。至於:「創造它的物體,負責摧毀它。」 ,非常正確,但這意味着我將不得不在每個命令中打開/關閉連接。我正在嘗試查看是否可能有辦法只在一個地方打開/關閉,即servlet。如果看起來絕對沒有辦法,那麼我會按照你所說的去做。 – shadesco 2012-04-20 04:59:40

+0

看到我的編輯,我爲你添加了一個可能的解決方案。 – Hiro2k 2012-04-20 05:06:54

+0

再次感謝,但我想你誤解了我的問題,你寫的是我已經在我的代碼中。現在的代碼是「Always」會打開一個連接,我想知道的是一個命令可能/可能不需要連接,如何將「連接」空對象傳遞給該命令,以及「There」打開一個連接,當流程返回到servlet時,關閉該servlet中的「連接」。 – shadesco 2012-04-20 05:24:29