I came up with a solution that solves my problem. I hope this is useful to someone there.
Thus, the main problem was limiting Hibernate to create a schema for a new client at runtime during a multi-tenant configuration.
"Hibernate does not support automatic export of a circuit in a tiered environment."
My solution to get around this limitation (using Spring) was to create a new LocalSessionFactoryBean that is set to NOT to support multi-tenancy. So basically I have two LocalSessionFactoryBeans.
- Multi-Tenant LocalSessionFactoryBean, which is used for multi-tenant sessions.
- Non Multi-Tenant LocalSessionFactoryBean, which is used to create tenant schemes using the configuration set in the spring file.
Spring Configuration
<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" /> <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> <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" /> <entry key="hibernate.multiTenancy" value="NONE" /> </map> </property> <property name="mappingResources"> <list> <TENANT SPECIFIC SCHEMA MAPPING RESOURCES /> </list> </property> </bean>
The 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 comes from Non Multi-Tenant LocalSessionFactoryBean
source share