如何在单个服务器上使用Hibernate与多个数据库

时间:2016-03-28 19:59:43

标签: java database spring hibernate

我们的应用程序允许我们的客户拥有多个数据库,所有数据库都在一个数据库服务器实例上运行。

例如,数据库可能是dbcommon,dbLive,dbStaging,dbUAT,dbDev,dbSandbox。公共数据库和生产数据库始终存在,但其他数据库是可选的(并且没有限制)。在dbcommon中有一个表告诉我们所有的数据库....所以我需要启动它。共同的表与其他表不同,其他表都具有相同的模式(订户数据)

使用Hibernate,我如何动态创建/使用Live或Staging(或任何其他)的连接?如果有帮助,我正在使用Spring。

我遇到了建议在配置中创建不同连接的答案,但由于订阅者数据库的数量可能不同(每次安装,而不是在应用程序运行时),这对我来说不是一个选项。

2 个答案:

答案 0 :(得分:1)

正如我在发布此问题后发现的那样,并且正如用户manish所建议的那样,Hibernate的Multi Tenancy支持(使用Database MultiTenancyStrategy)对我有用。我不得不使用各种资源(下面列出)拼凑出一个解决方案。

http://www.ticnfae.co.uk/blog/2014/07/16/hibernate-multi-tenancy-with-spring/

Setting up a MultiTenantConnectionProvider using Hibernate 4.2 and Spring 3.1.1

Multi-Tenancy with Spring + Hibernate: "SessionFactory configured for multi-tenancy, but no tenant identifier specified"

我仍然在寻找一种能够在租户数据库的同时引用公共(共享)数据库的方法......并且在完成后会尝试将其添加到此答案中。

答案 1 :(得分:0)

我能看到的最简单的方法是在Spring中通过配置文件管理所有内容。

我使用application.yml完成了这个。我也使用了Hikari连接池,但这并没有太多影响配置。

这是一个application.yml的示例,其中列出了3个配置文件,并且我已将其中两个配置文件作为示例。

spring:
  profiles:
    include: dev,test,production
    active: dev
---
spring:
  profiles: dev
oms:
  omsDataSource:
    driverClassName: com.informix.jdbc.IfxDriver
    jdbcUrl: jdbc:informix-sqli://devdb:9000/hol:INFORMIXSERVER=m_tcp_1;client_deve=en_US.8859-1;db_deve=en_US.8859-1;LOBCACHE=-1
    password: oms
    username: oms
    connectionTestQuery: select count(*) from systables
    maximumPoolSize: 5

---
spring:
  profiles: test
oms:
  omsDataSource:
    driverClassName: com.informix.jdbc.IfxDriver
    jdbcUrl: jdbc:informix-sqli://testdb:9000/hol:INFORMIXSERVER=m_tcp_1;client_deve=en_US.8859-1;db_deve=en_US.8859-1;LOBCACHE=-1
    password: oms
    username: oms
    connectionTestQuery: select count(*) from systables
    maximumPoolSize: 5

在我的数据库配置类中,我设置了JPA存储库,并告诉它使用什么entityManager。我还设置了配置属性来拉取application.yml。这意味着它将根据应用在启动时使用的配置文件交换详细信息。

@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactoryOms",
        transactionManagerRef = "transactionManagerOms",
        basePackages= "persistence.oms")
@Configuration
@ConfigurationProperties(prefix = "oms.omsDataSource")
public class omsDbConfig extends HikariConfig {

//This will automatically fill in the required fields from the application.yml. 
    @Bean
    public HikariDataSource orcaDataSource() throws SQLException {
        return new HikariDataSource(this);
    }

//I use that datasource to define my entityMangerFactory
@Bean(name = "entityManagerFactoryOms")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryOrca() throws SQLException {
        JpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        Properties props = new Properties();
        props.setProperty("hibernate.dialect","org.hibernate.dialect.InformixDialect");
        LocalContainerEntityManagerFactoryBean emfb =
                new LocalContainerEntityManagerFactoryBean();
        emfb.setDataSource(orcaDataSource());
        emfb.setPackagesToScan("persistence.oms");
        emfb.setJpaProperties(props);
        emfb.setJpaVendorAdapter(adapter);
        return emfb;
    }

    }

实体和存储库是正常定义的,那里没什么特别的。数据库将根据我告诉它运行的任何配置文件切换连接。

我只是将application.yml中的active个人资料转换为我需要的个人资料。

安全注意事项:定义生产配置文件,不要将生产作为默认配置文件。