2011-12-15 38 views
4

我們的應用程序使用Spring/Hibernate進行數據庫訪問。我們使用多個hibernate會話工廠(hibernate3.LocalSessionFactoryBean),因爲數據位於多個獨立的數據庫中。每個會話工廠都使用c3p0(c3p0.ComboPooledDataSource)配置了池式數據源。我可以在Spring/Hibernate/c3p0中爲多個數據庫使用一個池化數據源嗎?

碰巧,數據庫都駐留在同一個數據庫服務器上。我們的問題是,我們最終得到了許多數據庫連接池,都連接到同一臺服務器上。有沒有辦法共享一個共享數據源來訪問同一臺服務器上的多個數據庫?是否可以在會話工廠級別而不是在數據源級別配置jdbcUrl

或者這在實踐中不是一個真正的問題?是否可以配置多個數據庫連接池?

回答

0

我不認爲你可以這樣做。我不認爲我做到這一點。可以將它們視爲單獨的數據庫,也可以視爲一個。

如果它們是獨立的數據庫,它們會得到不同的連接池,需要由JTA進行管理,否則您需要設計整個系統來處理這些基礎之間的事務故障。

如果他們被視爲一個;您可以(如果您使用的是Oracle)創建一個連接池,然後使用別名和授權來啓用該單一連接來寫入其他兩個數據庫。

2

One Connection連接到一個數據庫。

如果您有2個數據庫,DB1和DB2,並且想要連接池,則需要爲這兩個數據庫準備好連接。

如果你實際上每個池有1個連接,C1和C2(我知道你有更多,但它是一樣的......) 肯定有可能把這兩個連接放在同一個連接池中。 然後你將有一個連接池與C1和C2。 你對連接池有什麼期望?對我來說 - >能夠給你隨機的已經準備好的連接,你可以直接使用,而不需要創建一個新連接的開銷。

現在猜猜看,如果您的獨特池中同時存在C1和C2,您將無法獲得「隨機」連接,因爲它們不屬於同一個數據庫......因此,您將擁有開銷檢查返回的連接是否指向期望的數據庫,或者您將有50%的機會在DB2上執行請求R1。因此,您可以簡單地製作自己的連接池實現,該連接池只使用2個子連接池CP1和CP2,並隨機使用這些子連接池之一的getConnection,但是,之後必須檢查你使用正確的連接池,所以你最好保持分開2個不同的連接池。

我不知道你爲什麼只想要一個連接池。也許你希望能夠告訴你的應用程序「所有連接池都有100個連接」,並且你希望你的應用程序能夠自動設置每個游泳池中優化的連接數量?對我來說似乎是可能的,但我不知道是否有一個已經存在的泛型實現,也許你可以做一個連接池包裝,它將在所有現有池之間共享使用的平均連接百分比,然後調整池大小或像那樣的東西...


對我來說,在你的應用程序中有多個連接池是完全沒問題的。 除了在同一個應用程序中使用兩個不同的數據庫(Oracle + MongoDB或類似的東西)以外,使用2個在同一臺服務器上使用2個Oracle數據庫模式的連接池也是完全可以的,甚至如果兩個數據庫都有完全相同的表。


你應該看看的(一般B2B)的SaaS應用與多個客戶多租戶策略: - 一個是有一個DB每一個客戶,有一個具有塔「CUSTOMER_ID」每個表。維護起來更容易,但表中有更多的行(但顯然你可以索引該customer_id列) - 另一個可能是你做的:每個客戶有一個數據庫/數據源/連接池/ sessionfactory,每個數據庫都有相同的表。最終你會有一些像「定製的主要sessionfactory」一樣的機制,它將使用存儲customerId的ThreadLocal(由某些憑證過濾器設置)來選擇合適的子sessionfactory。

看看下面的文章爲例(有很多關於這個問題的): http://relation.to/Bloggers/MultitenancyInHibernate

public class MyTenantAwareConnectionProvider implements ConnectionProvider { 
    public static final String BASE_JNDI_NAME_PARAM = "MyTenantAwareConnectionProvider.baseJndiName"; 

    private String baseJndiName; 

    public void configure(Properties props) { 
     baseJndiName = props.getProperty(BASE_JNDI_NAME_PARAM); 
    } 

    public Connection getConnection() throws SQLException { 
     final String tenantId = TenantContext.getTenantId() 
     final String tenantDataSourceName = baseJndiName + '/' + tenantId; 
     DataSource tenantDataSource = JndiHelper.lookupDataSource(tenantDataSourceName); 
     return tenantDataSource.getConnection(); 
    } 

    public void closeConnection(Connection conn) throws SQLException { 
     conn.close(); 
    } 

    public boolean supportsAggressiveRelease() { 
     // so long as the tenant identifier remains available in TL throughout, we can 
     return true; 
    } 

    public close() { 
     // currently nothing to do here 
    } 
} 

這幾乎是我告訴你的,只是在這裏有一個動態連接提供商,而不是動態的會話提供者。 (租客這裏=在我的客戶爲例)

可以發現,有在本例沒有連接池,但你一定可以實現自己的PooledMyTenantAwareConnectionProvider;)

好運。

相關問題