2009-11-02 37 views
2

在我的一個項目中,我有一個管理多個客戶的應用程序(或者客戶,如果您願意的話)。對於它們中的每一個,我都有一個專用的數據庫模式。但是,應用程序一次只處理一個客戶端,即用戶必須從應用程序中的一個客戶端切換到另一個客戶端(在運行時,不重新啓動應用程序)才能訪問來自此新客戶端的數據。如何用Hibernate處理幾個DB模式?

對於這類項目,您將如何管理連接以及持久層?

我想爲此使用Hibernate。處理多個數據庫/模式時,我必須非常小心的是什麼?

在這種情況下春季會有什麼幫助嗎?


如果我不夠清楚,讓我以一個例子來解釋情況。假設我的應用程序可以處理兩個客戶端:clientONEclientTWO。 我已經實現了一個類,可以爲給定的客戶端提供數據庫模式,用戶,密碼和連接字符串。

每個客戶都有一個債務人清單,但不幸的是,對於clientONEclientTWO,DEBTOR表結構並不相同。 即使表/列的名稱是不一樣的......

所以我可以爲每個客戶端(我使用Hibernate的註解)一個債務人類:

@Entity 
@Table(name = "T_DEBTOR_ONE") 
... 
public class ClientOneDebtor { 

    @Id 
    @Column(name = "ID_DEBTOR") 
    private String idDebtor; 

    ... 

} 

和:

@Entity 
@Table(name = "T_DEBTOR_TWO") // Table names are not the same among the different schemas... 
... 
public class ClientTwoDebtor { 

    @Id 
    @Column(name = "DEBTOR_ID") // It's just to show that the same information is stored in a column that has not the same name. 
    private String idDebtor; 

    ... 

} 

理想情況下,我會嘗試有一個共同的Debtor類(這裏是一個抽象類,但我可以使用一個接口):

public abstract class AbstractDebtor { 

    public abstract String getIdDebtor(); 

    ... 

} 


@Entity 
@Table(name = "T_DEBTOR_ONE") 
... 
public class ClientOneDebtor extends AbstractDebtor { 

    @Id 
    @Column(name = "ID_DEBTOR") 
    private String idDebtor; 

    ... 

} 


@Entity 
@Table(name = "T_DEBTOR_TWO") 
... 
public class ClientTwoDebtor extends AbstractDebtor { 

    @Id 
    @Column(name = "DEBTOR_ID") // It's just to show that the same information is stored in a column that has not the same name. 
    private String idDebtor; 

    ... 

} 

這樣,我可以更容易地操作DAO /服務層中的Debtor對象,因爲我不需要爲每個客戶端複製我的DAO和服務。 例如,從DAO獲取所有債務人清單的方法將是public List<AbstractDebtor> getAllDebtors() { ... }

那麼,當我更改由我的應用程序管理的客戶端時,如何更改上下文? 換句話說,我將如何向Hibernate(或Spring?)表明我想使用正確的持久性對象(ClientOneDebtorClientTwoDebtor)來關於當前由我的應用程序管理的客戶端?

如果你認爲我在錯誤的方向我要去,不要猶豫,分享您對如何解決這類問題的想法...


關於第一答案編輯:

我需要處理的不同模式的數量在15-20左右。除此之外,我只需要映射其表格的一小部分。

我也知道每個客戶/客戶擁有一個模式並不是存儲數據的最佳解決方案。然而,這種架構自5年以來就存在了,而且我們可能在下一年只有一種模式(在最好的情況下)。)。

回答

1

如果每次只需要一個,那麼它就更簡單了。只需爲每個數據庫創建一個SessionFactory。避免採用HibernateUtils靜態SessionFactory實例方法,您不會遇到任何問題。

一個巧妙的辦法與Spring這樣做,如果你沒有太多的數據庫(上百個)爲實例化一個單獨的春天ApplicationContext爲包含SessionFactoryBeanDataSource配置專門針對該數據庫每一個。

你可以使用像PropertyOverrideConfigurer這樣的彈簧機制和一個普通父母ApplicationContext來分解所有常見的東西,這樣你的許多小孩子就可以小型化並且可以維護。

然後,當一個請求時,只需選擇你ApplicationContext要處理,並開始拉豆子出來。

如果您想在沒有使用Spring的情況下執行此操作,還可以創建多個SessionFactory實例並將「當前」實例存儲在一個靜態的ThreadLocal中。

0

從我的經驗來看,對於不同的客戶/用戶/公司/任何不同的架構從來都不是一個好主意。你有多少這樣的模式? 2? 5? 100?

在我們有兩個或多個模式(託管它們放在不同的服務器或訪問DB的由第三方作爲典型usecases託管),我們只是爲他們每個人的配置獨立的會話工廠的應用。選擇正確的是被注入DAO的會話工廠「隱式完成」。因此,對於你的情況,你可能有一個clientOneDetborDAO和一個clientTwoDebtorDAO--儘管如此,這對於100個客戶端來說很難實現;)

0

不幸的是,現實世界往往確實需要多個數據庫/模式,尤其是當你有一個供應商的產品,其數據庫必須從公司的數據庫不同。

製作的數據庫任意數量將是一個爛攤子,而對於這一點,你真的應該考慮一個更好的形式數據的組織。但是對於一個固定的(希望很小的)一組數據庫,只需在持久化配置中定義它們,併爲每個數據庫分別設置一個PersistenceUnit(這意味着一個單獨的EntityManager)。

使用你所說明的繼承方案,假定框架允許你爲每個派生類分配合適的EntityManager。