Hibernate多租户在运行时创建模式

8
我正在使用Hibernate 4和Spring 4为Java Web应用程序设置多租户支持。在应用程序启动时,将创建并设置默认模式。当不尝试支持多租户时,此模式可以正常工作。
现在我需要做的是为每个创建帐户的新租户创建一个模式。由于它将遵循相同的格式,因此此模式可以简单地是公共模式的副本。
如何在运行时创建遵循默认模式相同格式的新模式?似乎默认模式是在实例化LocalSessionFactoryBean时创建的,因为那里我指定了映射资源。
2个回答

6
我想出了一个解决方案,解决了我的问题。我希望它对其他人有用。
因此,主要问题在于在多租户配置中,在运行时为新客户端创建模式的Hibernate限制。
“Hibernate不支持在多租户环境中自动模式导出。”
我的解决方法(使用Spring)是创建一个新的LocalSessionFactoryBean,该bean配置为不支持多租户。因此,我基本上有两个LocalSessionFactoryBeans。
1. 用于多租户会话的Multi-Tenant LocalSessionFactoryBean 2. 用于使用在spring文件中设置的配置为租户创建模式的非多租户LocalSessionFactoryBean。
Spring配置
<!-- 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>


用于创建模式的代码

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

请注意,此代码中的_configuration来自非多租户LocalSessionFactoryBean。

知道您已经解决了这个问题一段时间,但是如果您能提供更多细节(例如如何注入/创建非多租户本地会话工厂Bean,甚至源代码),那将不胜感激! - Jordan Mackie

1

感谢您的建议。我们计划仅使用Hibernate来配置我们的持久性。 Hibernate文档仅显示顶级类,不显示连接所有内容所需的实现。 - kerl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接