How to configure multiple DataSources for multitenancy in Hibernate

醉酒当歌 提交于 2019-11-30 12:20:12

问题


I am trying to add multitenancy to a java application using the separate schema approach as outlined in this webinar

I wanted to know how would I configure multiple data sources via spring perhaps by using properties files and get the data sources from the spring context based on tenant id.

More importantly, though I want to be able to configure my custom connection provider implementation that supports this multitenancy feature to be used by Hibernate instead of the injected ConnectionProvider that it uses by default.

How can i achieve this.


回答1:


Use the AbstractRoutingDataSource. See my answer located @ Multiple Entity Manager issue in Spring when using more than one datasource.




回答2:


This post demonstrate how to use spring security and AbstractRoutingDataSource to build up Multi-Tenancy SaaS applications. Extend Spring Security to Protect Multi-tenant SaaS Applications




回答3:


If you want to do multi-tenancy by ConnectionProvider, you'll need a thread-local to provide context. See this brief run-through:

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




回答4:


As I explained in this article, the routing can be done by Hibernate via its MultiTenancyConnectionProvider which you can implement like this:

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
        );
    }
}

Assuming each tenant uses its own dedicated DataSource, you can register the individual ConnectionProviders using a utility method like this one:

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
    );
}

You can register a default tenant for admin-related tasks:

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

And for the actual tenants, you could use a method like this one:

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
    );
}

You can change the MysqlDataSource to whatever database you are using.

Then, registering the tenants is as simple as that:

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

The last thing to take into consideration is to provide the MultiTenancyConnectionProvider implementation to Hibernate via the hibernate.multi_tenant_connection_provider configuration property.

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


来源:https://stackoverflow.com/questions/6804738/how-to-configure-multiple-datasources-for-multitenancy-in-hibernate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!