如何使用Hibernate处理多个数据库模式?

时间:2009-11-02 16:56:37

标签: java hibernate persistence database-connection

在我的一个项目中,我有一个管理多个客户端的应用程序(如果您愿意,还可以管理客户)。对于他们每个人,我在数据库上有一个专用的模式。 但是,应用程序一次只处理一个客户端,即用户必须在应用程序中从一个客户端切换到另一个客户端(在运行时,不重启应用程序),以便从这个新客户端访问数据。

您将如何管理此类项目的连接以及持久层?

我想使用Hibernate。在处理多个数据库/模式时,我必须非常小心的要点是什么?

在这种情况下Spring可以提供任何帮助吗?


如果我不够清楚,让我用一个例子解释一下情况。 想象一下,我的应用程序可以处理两个客户端:clientONEclientTWO。 我已经实现了一个类,它可以为我提供给定客户端的数据库模式,用户,密码和连接字符串。

每个客户都有一个债务人列表,但遗憾的是,clientONEclientTWO的DEBTOR表结构并不相同。 甚至表/列的名称也不一样......

所以我可以为每个客户端创建一个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 / Service层中的Debtor对象,因为我不需要为每个客户端复制我的DAO和服务。 例如,DAO获取所有债务人列表的方法将为public List<AbstractDebtor> getAllDebtors() { ... }

那么,当我更改应用程序管理的客户端时,如何更改上下文? 换句话说,我如何向Hibernate(或Spring?)指出我想使用正确的持久性对象(ClientOneDebtorClientTwoDebtor)关于我的应用程序当前管理的客户端?

如果您认为我的方向错误,请不要犹豫,分享您对如何解决此类问题的看法......


编辑第一个答案:

我需要处理的不同模式的数量大约是15 - 20.除此之外,我只需要映射其表的一小部分。

我也知道每个客户/客户拥有一个模式并不是存储数据的最佳解决方案。但是,这种架构存在5年以来,我们可能会在明年转移到一个架构(在最好的情况下;))。

2 个答案:

答案 0 :(得分:1)

如果每次只需要一个,那么它就会变得更简单。只需为每个数据库创建一个SessionFactory。避免使用HibernateUtils静态SessionFactory实例方法,您将不会遇到任何问题。

如果没有太多数据库(数百个),使用Spring执行此操作的一种巧妙方法是为包含ApplicationContext和{{1}的每个数据库实例化单独的Spring SessionFactoryBean配置专门用于该数据库。

您可以使用DataSource之类的Spring机制和公共父PropertyOverrideConfigurer来分解所有常见内容,以便您的多个孩子ApplicationContext小而且易于维护。

然后当一个请求进来时,只需选择你想要使用的ApplicationContext并开始拉出它。

如果您想在没有Spring的情况下执行此操作,您还可以创建多个ApplicationContext实例,并将“当前”实例存储在静态SessionFactory中。

答案 1 :(得分:0)

不幸的是,真实世界通常需要多个数据库/模式,尤其是当您的供应商产品的数据库必须与公司数据库不同时。

制作任意数量的数据库将是一团糟,为此,您真的应该考虑更好的数据组织形式。但是对于一组固定(希望很小)的数据库,只需在持久性配置中定义它们,每个数据库都有一个单独的PersistenceUnit(这意味着一个单独的EntityManager)。

使用图示的继承方案,您可以为每个派生类分配适当的EntityManager,假设框架允许您。