我正在使用hibernate 4和spring 4为Java Web应用程序设置多租户支持。默认模式是在应用程序启动时创建和设置的。当不尝试支持多租户时,此架构可以正常工作。
现在,我需要为每个创建帐户的新租户创建一个架构。该模式可以简单地是通用模式的副本,因为它将遵循相同的格式。
如何在运行时创建与默认架构相同格式的新架构?似乎在实例化LocalSessionFactoryBean时创建了默认模式,因为这是我指定映射资源的地方。
我想出了解决我的问题的解决方案。我希望这对外面的人有用。
因此,主要问题归结为Hibernate的限制,即在多租户配置中在运行时为新客户端创建模式。
“ Hibernate在多租户环境中不支持自动模式导出。”
为了解决此限制(使用Spring),我的解决方案是创建一个新的LocalSessionFactoryBean,将其配置为不支持多租户。所以基本上我有两个LocalSessionFactoryBeans。
弹簧配置
<!-- 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来自Non-Tenant LocalSessionFactoryBean