Hibernate多租户在运行时创建模式 [英] Hibernate multi-tenancy create schema during runtime

查看:175
本文介绍了Hibernate多租户在运行时创建模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用hibernate 4和spring 4为java web应用程序设置多租户支持。默认架构在应用程序启动时创建并设置。当不试图支持多租户时,这种模式运行良好。



我现在需要做的是为每个创建帐户的新租户创建一个模式。该模式可以简单地作为通用模式的副本,因为它将遵循相同的格式。

如何在运行时创建遵循与默认模式相同格式的新模式?看起来,当LocalSessionFactoryBean被实例化时,默认模式被创建,因为那是我指定映射资源的地方。

用解决方案解决我的问题。我希望它对那里的人有用。



所以主要问题归结为Hibernate限制在多租户运行时为新客户创建模式配置。


Hibernate不支持在多租户环境中自动导出模式。
blockquote>



解决此限制(使用Spring)的解决方案是创建一个新的LocalSessionFactoryBean,它被配置为不支持多租户。
所以基本上我有两个LocalSessionFactoryBeans。


  1. 用于多租户会话的多租户LocalSessionFactoryBean
  2. 非多租户LocalSessionFactoryBean用于使用spring文件中的配置集为租户创建模式。



Spring配置

 <! - 多租户SessionFactory  - > 
< bean id =sessionFactory
class =org.springframework.orm.hibernate4.LocalSessionFactoryBean>
< property name =dataSourceref =dataSource/>
< property name =hibernateProperties>
< map>
< entry key =hibernate.dialectvalue =$ {hibernate.dialect}/>
< entry key =hibernate.hbm2ddl.autovalue =NONE/>
<! - 多租户支持 - >
< entry key =hibernate.multiTenancyvalue =SCHEMA/>
< entry key =hibernate.tenant_identifier_resolvervalue =$ {hibernate.tenant_identifier_resolver}/>
< entry key =hibernate.multi_tenant_connection_providervalue-ref =multiTenantConnectionProvider/>
< / map>
< / property>
< property name =mappingResources>
< list>
<公共模式映射资源/>
< / list>
< / property>
< / bean>

<! - - 能够管理多租户模式的SessionFactory - >
< bean id =sessionFactorySchemaManager
class =org.springframework.orm.hibernate4.LocalSessionFactoryBean>
< property name =dataSourceref =dataSource/>
< property name =hibernateProperties>
< map>
< entry key =hibernate.dialectvalue =$ {hibernate.dialect}/>
< entry key =hibernate.hbm2ddl.autovalue =CREATE/>
<! - 多租户支持 - >
< entry key =hibernate.multiTenancyvalue =NONE/>
< / map>
< / property>
< property name =mappingResources>
< list>
<租户特定模式映射资源/>
< / list>
< / property>
< / bean>





用于创建模式的代码



$ $ $ $ $ $ $ $ $ $ $ $ $ $ $;
$ b $ if(_configuration!= null&& _dataSource!= null){

//获取本地配置以配置
final配置tenantConfig = _configuration;

//设置这个配置的属性
属性props = new Properties();
props.put(Environment.DEFAULT_SCHEMA,tenantId);
tenantConfig.addProperties(道具);
$ b $ //获取连接
连接连接= DriverManager.getConnection(_dataSource.getUrl(),
_dataSource.getUsername(),_dataSource.getPassword());

//创建模式
connection.createStatement()。execute(CREATE SCHEMA+ tenantId +);

//从配置
运行模式更新SchemaUpdate schemaUpdate = new SchemaUpdate(tenantConfig);
schemaUpdate.execute(true,true);

//设置模式
connection.createStatement()。execute(SET SCHEMA+ tenantId +);

//设置结果
result = true;
$ b $ else if(_configuration == null){
if(_LOGGER.isWarnEnabled()){
_LOGGER.warn(No configuration is specified for+ getClass() .getSimpleName());
}
} else if(_dataSource == null){
if(_LOGGER.isWarnEnabled()){
_LOGGER.warn(No dataSource was specified for+ getClass( ).getSimpleName());
}
}

返回结果;
}



请注意,此代码中的_configuration来自Non Multi-Tenant LocalSessionFactoryBean


I am setting up multi-tenant support for a java web application using hibernate 4 and spring 4. The default schema is created and set when the application starts. This schema works fine when not trying to support multi-tenancy.

What I need to do now is to create a schema for each new tenant that creates an account. This schema can simply be a copy of the common schema because it will adhere to the same format.

How can I create new schemas that follow the same format as the default schema during runtime? It appears that the default schema is created when the LocalSessionFactoryBean is instantiated since that is where I specify the mapping resources.

解决方案

I came up with a solution that solves my problem. I hope it is useful to someone out there.

So the main problem came down to the Hibernate restriction of creating a schema for a new client during runtime while in multi-tenant configuration.

"Hibernate does not support automatic schema export in a multi-tenancy environment."


My solution to get around this restriction (using Spring) was to create a new LocalSessionFactoryBean that is configured to NOT to support multi-tenancy. So basically I have two LocalSessionFactoryBeans.

  1. Multi-Tenant LocalSessionFactoryBean that is used for multi-tenant sessions
  2. Non Multi-Tenant LocalSessionFactoryBean that is used to create schemas for tenants using the configuration set in the spring file.


Spring configuration

<!-- Multi-tenant SessionFactory -->
<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="hibernateProperties">
        <map>
            <entry key="hibernate.dialect" value="${hibernate.dialect}" />
            <entry key="hibernate.hbm2ddl.auto" value="NONE" />
            <!-- Multi-tenancy support -->
            <entry key="hibernate.multiTenancy" value="SCHEMA" />
            <entry key="hibernate.tenant_identifier_resolver" value="${hibernate.tenant_identifier_resolver}" />
            <entry key="hibernate.multi_tenant_connection_provider" value-ref="multiTenantConnectionProvider" />
        </map>
    </property>
    <property name="mappingResources">
        <list>
            <COMMON SCHEMA MAPPING RESOURCES />
        </list>
    </property>
</bean>

<!-- SessionFactory capable of managing multi-tenant schemas -->
<bean id="sessionFactorySchemaManager"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="hibernateProperties">
        <map>
            <entry key="hibernate.dialect" value="${hibernate.dialect}" />
            <entry key="hibernate.hbm2ddl.auto" value="CREATE" />
            <!-- Multi-tenancy support -->
            <entry key="hibernate.multiTenancy" value="NONE" />
        </map>
    </property>
    <property name="mappingResources">
        <list>
            <TENANT SPECIFIC SCHEMA MAPPING RESOURCES />
        </list>
    </property>
</bean>


Code used to create the schema

public boolean createSchema(final String tenantId) throws SQLException {
    boolean result = false;

    if(_configuration != null && _dataSource != null) {

        // Get a local configuration to configure
        final Configuration tenantConfig = _configuration;

        // Set the properties for this configuration
        Properties props = new Properties();
        props.put(Environment.DEFAULT_SCHEMA, tenantId);
        tenantConfig.addProperties(props);

        // Get connection
        Connection connection = DriverManager.getConnection(_dataSource.getUrl(), 
                _dataSource.getUsername(), _dataSource.getPassword());

        // Create the schema
        connection.createStatement().execute("CREATE SCHEMA " + tenantId + "");

        // Run the schema update from configuration
        SchemaUpdate schemaUpdate = new SchemaUpdate(tenantConfig);
        schemaUpdate.execute(true, true);

        // Set the schema
        connection.createStatement().execute("SET SCHEMA " + tenantId + "");

        // Set the result
        result = true;

    } else if(_configuration == null) {
        if(_LOGGER.isWarnEnabled()) {
            _LOGGER.warn("No configuration was specified for " + getClass().getSimpleName());
        }
    } else if(_dataSource == null) {
        if(_LOGGER.isWarnEnabled()) {
            _LOGGER.warn("No dataSource was specified for " + getClass().getSimpleName());
        }
    }

    return result;
}


Note that the _configuration in this code came from the Non Multi-Tenant LocalSessionFactoryBean

这篇关于Hibernate多租户在运行时创建模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆