2010-08-06 143 views
9

我正在研究一個需要連接N個數據庫系統[N個範圍在1到350之間的任何地方]的應用程序。JDBC - 連接多個數據庫

的想法是 - 用戶將數據庫列表呈現,並會被要求選擇任一或所有從列表中的數據庫。

一旦數據庫被選擇,我需要連接到每個數據庫並執行的存儲過程。

我打算用普通的舊JDBC並獲得他們每個人一個時間的[或由多個線程運行它們]連接並執行存儲過程並關閉連接。

而這一切都應該發生在交易中。做這個的最好方式是什麼?

如果不是JDBC ......任何其他有效的方式?

更新 -

的存儲過程是實際參與運行一些SQL - 例如更新列的權限授予用戶等

+1

什麼樣的應用?桌面還是網頁? – skaffman 2010-08-06 21:10:14

+0

這是一個Web應用程序。 – jagamot 2010-08-06 21:17:42

+0

我的理解是,你不需要在一次交易中做到這一點,這是真的嗎?除此之外還需要考慮更多。 – BalusC 2010-08-06 21:55:49

回答

3

我想創建一個線程池有一個合理的最高金額線程,在10到20個線程之間,可以在Executors#newFixedThreadPool()的幫助下調用單獨的DB連接和SP執行任務,每個任務都使用ExecutorService#invokeAll()作爲Callable。你想玩的線程數和個人資料,畢竟產生最好的表現。

每個Callable實施應採取的連接細節和SP的名稱作爲構造函數的參數,這樣就可以重新使用不同的數據庫調用相同的實現。


更新:OK,這是一個web應用。你不想浪費線程。如果它應該被單個併發用戶使用,那麼你應該確保在請求結束時或者在會話的最高端線程池正確地爲shutdown。但是,如果它應該被多個併發用戶使用,那麼你想在應用程序範圍內共享線程池。同樣在這裏,你需要確保它在webapp關閉時正確關閉。 ServletContextListener在這裏很有用。

0

這聽起來像是一團糟,但這是你的問題。

您需要每個數據庫一個連接池。我不會建議您嘗試自己處理連接生命週期。讓應用服務器爲你做。

如果您希望一組數據庫參與一個大事務,那麼您必須使用它們的所有的JDBC XA驅動程序。您還需要JTA交易管理器來爲您監督交易。

的存儲過程中不能包含任何邏輯來處理交易;你必須讓JTA去做。

你不說什麼存儲過程正在做什麼。如果它不需要返回任何東西,另一種設計可能是JMS,一個隊列和一個監聽器池。如果我是你,我會擔心線程。我會找到一種方法讓容器爲我做些複雜的事情。

+0

我猜所有的數據庫連接URL都保存在中央數據庫中。我相信我們不想在應用程序服務器中創建數據源[如前所述,我有大約1 - 350個數據源] .....在這種情況下,我想我需要自己處理連接生命週期嗎? – jagamot 2010-08-06 21:57:02

1

正如duffymo在他的評論中所指出的那樣,如果你有一個事務協調器和兩個階段提交,你將只能在多個數據庫上執行事務。

爲此,您將需要一個將處理JTA的J2EE堆棧。如果您在Tomcat或另一個沒有JTA的容器中運行,則可以下載和安裝多個選項。

當然,您需要讓容器而不是數據庫/存儲過程處理事務提交和回滾。

2

如果您可以使用兩個連接,請使用連接池c3p0來管理它們。要連接兩個數據庫,我宣佈:

public Connection connection1; 
public Connection connection2; 
DataSource dataSource1; 
DataSource dataSource2; 

然後兩個類似的方法:

public Connection dbConnect1() throws SQLException { 
    ComboPooledDataSource cpds = new ComboPooledDataSource(); 
    try { 
     cpds.setDriverClass("com.mysql.jdbc.Driver"); 
    } catch (PropertyVetoException e) { 
    } 
    cpds.setJdbcUrl("jdbc:mysql://localhost:3306/myDatabase1?autoReconnect=true"); 
    cpds.setUser("myMYSQLServerLogin"); 
    cpds.setPassword("myMYSQLServerPassword"); 
    cpds.setMinPoolSize(5); 
    cpds.setAcquireIncrement(5); 
    cpds.setMaxPoolSize(20); 
    cpds.setMaxIdleTime(60); 
    cpds.setMaxStatements(100); 
    cpds.setPreferredTestQuery("SELECT 1"); 
    cpds.setIdleConnectionTestPeriod(60); 
    dataSource1 = cpds; 
    connection1 = dataSource1.getConnection(); 
    return connection1; 
} 

public Connection dbConnect2() throws SQLException { 
    ComboPooledDataSource cpds = new ComboPooledDataSource(); 
    try { 
     cpds.setDriverClass("com.mysql.jdbc.Driver"); 
    } catch (PropertyVetoException e) { 
    } 
    cpds.setJdbcUrl("jdbc:mysql://localhost:3306/myDatabase2?autoReconnect=true"); 
    cpds.setUser("myMYSQLServerLogin"); 
    cpds.setPassword("myMYSQLServerPassword"); 
    cpds.setMinPoolSize(5); 
    cpds.setAcquireIncrement(5); 
    cpds.setMaxPoolSize(20); 
    cpds.setMaxIdleTime(60); 
    cpds.setMaxStatements(100); 
    cpds.setPreferredTestQuery("SELECT 1"); 
    cpds.setIdleConnectionTestPeriod(60); 
    dataSource2 = cpds; 
    connection2 = dataSource2.getConnection(); 
    return connection2; 
} 
+0

只需在350個數據庫的一個循環中執行此操作。如果需要清理代碼,請從主數據庫提取每個數據庫的參數。 – Zon 2014-05-02 16:54:42