【问题标题】:Hibernate multi-tenancy create schema during runtimeHibernate 多租户在运行时创建模式
【发布时间】:2015-04-22 09:56:19
【问题描述】:

我正在使用 hibernate 4 和 spring 4 为 java web 应用程序设置多租户支持。默认模式是在应用程序启动时创建和设置的。当不尝试支持多租户时,此架构可以正常工作。

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

如何在运行时创建与默认模式相同格式的新模式?似乎在实例化 LocalSessionFactoryBean 时会创建默认架构,因为这是我指定映射资源的地方。

【问题讨论】:

    标签: java spring hibernate multi-tenant


    【解决方案1】:

    我想出了一个解决我的问题的解决方案。我希望它对那里的人有用。

    因此,主要问题归结为 Hibernate 限制,即在运行时期间在多租户配置中为新客户端创建模式。

    “Hibernate 不支持多租户环境中的自动模式导出。”


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

    1. 用于多租户会话的多租户 LocalSessionFactoryBean
    2. 非多租户 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

    【讨论】:

    • 知道您刚才解决了这个问题,但如果您能提供更多详细信息(例如如何注入/创建非多租户 localsessionfactorybean,甚至是非常感谢的源代码!
    【解决方案2】:

    您可以使用 eclipseLink 解决您的问题。 这是一些实用链接: https://wiki.eclipse.org/EclipseLink/Examples/JPA/Multitenanthttp://www.javacodegeeks.com/2012/02/sneak-peak-at-java-ee-7-multitenant.html 或者如果你想使用休眠,你可以看看这个: http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html/ch16.html 还有这个关于休眠多租户的示例:https://gist.github.com/dipold/5700724http://www.devx.com/Java/Article/47817

    【讨论】:

    • 感谢您的建议。我们计划只使用休眠来配置我们的持久性。 hibernate 文档仅显示顶级类,并没有显示将所有内容连接在一起所需的实现。
    猜你喜欢
    • 2019-06-23
    • 2021-03-20
    • 2022-10-04
    • 2021-06-07
    • 1970-01-01
    • 1970-01-01
    • 2020-11-02
    • 2022-07-13
    • 2023-04-01
    相关资源
    最近更新 更多