如何在Hibernate中为多租户配置多个DataSource

时间:2011-07-24 03:21:48

标签: hibernate spring multi-tenant

我正在尝试使用this webinar

中概述的单独模式方法将多租户添加到Java应用程序

我想知道如何通过spring配置多个数据源,可能是使用属性文件,并根据租户ID从spring上下文中获取数据源。

更重要的是,虽然我希望能够配置我的自定义连接提供程序实现,该实现支持Hibernate使用的多租户功能,而不是默认情况下使用的注入ConnectionProvider

我怎样才能实现这一点。

4 个答案:

答案 0 :(得分:4)

使用AbstractRoutingDataSource。请参阅@ Multiple Entity Manager issue in Spring when using more than one datasource的答案。

答案 1 :(得分:2)

这篇文章演示了如何使用spring security和AbstractRoutingDataSource构建多租户SaaS应用程序。 Extend Spring Security to Protect Multi-tenant SaaS Applications

答案 2 :(得分:1)

如果您想通过ConnectionProvider进行多方租用,则需要一个本地线程来提供上下文。请参阅此简要介绍:

http://literatejava.com/hibernate/multi-tenancy-architecture-with-hibernate/

答案 3 :(得分:1)

正如我在this article中所解释的那样,路由可以由Hibernate通过其MultiTenancyConnectionProvider完成,您可以这样实现:

public class MultiTenantConnectionProvider
        extends AbstractMultiTenantConnectionProvider {

    public static final MultiTenantConnectionProvider INSTANCE =
            new MultiTenantConnectionProvider();

    private final Map<String, ConnectionProvider> connectionProviderMap = 
            new HashMap<>();

    Map<String, ConnectionProvider> getConnectionProviderMap() {
        return connectionProviderMap;
    }

    @Override
    protected ConnectionProvider getAnyConnectionProvider() {
        return connectionProviderMap.get(
            TenantContext.DEFAULT_TENANT_IDENTIFIER
        );
    }

    @Override
    protected ConnectionProvider selectConnectionProvider(
            String tenantIdentifier) {
        return connectionProviderMap.get(
            tenantIdentifier
        );
    }
}

假设每个租户都使用自己专用的DataSource,则可以使用如下实用程序方法来注册单个ConnectionProviders

private void addTenantConnectionProvider(
        String tenantId, 
        DataSource tenantDataSource, 
        Properties properties) {

    DatasourceConnectionProviderImpl connectionProvider = 
        new DatasourceConnectionProviderImpl();
    connectionProvider.setDataSource(tenantDataSource);
    connectionProvider.configure(properties);

    MultiTenantConnectionProvider.INSTANCE
    .getConnectionProviderMap()
    .put(
        tenantId, 
        connectionProvider
    );
}

您可以为管理员相关任务注册默认租户:

addTenantConnectionProvider(
    TenantContext.DEFAULT_TENANT_IDENTIFIER, 
    defaultDataSource, 
    properties()
);

对于实际的租户,您可以使用如下方法:

private void addTenantConnectionProvider(
        String tenantId) {

    DataSourceProvider dataSourceProvider = database()
    .dataSourceProvider();

    Properties properties = properties();

    MysqlDataSource tenantDataSource = new MysqlDataSource();
    tenantDataSource.setDatabaseName(tenantId);
    tenantDataSource.setUser(dataSourceProvider.username());
    tenantDataSource.setPassword(dataSourceProvider.password());

    properties.put(
        Environment.DATASOURCE,
        dataSourceProxyType().dataSource(tenantDataSource)
    );

    addTenantConnectionProvider(
        tenantId, 
        tenantDataSource, 
        properties
    );
}

您可以将MysqlDataSource更改为您正在使用的任何数据库。

然后,注册租户就这么简单:

addTenantConnectionProvider("asia");
addTenantConnectionProvider("europe");

要考虑的最后一件事是通过MultiTenancyConnectionProvider配置属性为Hibernate提供hibernate.multi_tenant_connection_provider实现。

properties.put(
    AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER, 
    MultiTenantConnectionProvider.INSTANCE
);