Я пытаюсь настроить многопользовательское веб-приложение, причем (в идеале) возможность как для разделения базы данных, так и для разделения схем. Хотя я собираюсь начать с разделения Схемы. В настоящее время мы используем:
- Spring 4.0.0
- Hibernate 4.2.8
- Hibernate-c3p0 4.2.8 (который использует c3p0-0.9.2.1)
- и PostgreSQL 9.3 (что я сомневаюсь, что это действительно важно для общей архитектуры)
В основном я следил за этот поток (из-за решения для @Transactional
). Но я немного потерял в реализации MultiTenantContextConnectionProvider
. Существует также этот подобный вопрос, заданный здесь на SO, но есть некоторые аспекты, которые я не могу понять:
1) Что происходит с пулом соединений? Я имею в виду, он управляется Spring или Hibernate? Я предполагаю, что с ConnectionProviderBuilder
- или, как было предложено, - любой из его реализации, Hibernate - это тот парень, который его управляет.
2) Хороший подход, который Spring не управляет пулом соединений? или возможно ли, что Spring справится с этим?
3) Является ли это правильным путем для будущего внедрения разделения баз данных и схем?
Любые комментарии или описания полностью оценены.
приложения context.xml
<beans>
...
<bean id="dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
<property name="targetDataSource" ref="c3p0DataSource" />
</bean>
<bean id="c3p0DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="org.postgresql.Driver" />
... other C3P0 related config
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="packagesToScan" value="com.webapp.domain.model" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
<prop key="hibernate.default_schema">public</prop>
<prop key="hibernate.multiTenancy">SCHEMA</prop>
<prop key="hibernate.tenant_identifier_resolver">com.webapp.persistence.utility.CurrentTenantContextIdentifierResolver</prop>
<prop key="hibernate.multi_tenant_connection_provider">com.webapp.persistence.utility.MultiTenantContextConnectionProvider</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="autodetectDataSource" value="false" />
<property name="sessionFactory" ref="sessionFactory" />
</bean>
...
</beans>
CurrentTenantContextIdentifierResolver.java
public class CurrentTenantContextIdentifierResolver implements CurrentTenantIdentifierResolver {
@Override
public String resolveCurrentTenantIdentifier() {
return CurrentTenantIdentifier; // e.g.: public, tid130, tid456, ...
}
@Override
public boolean validateExistingCurrentSessions() {
return true;
}
}
MultiTenantContextConnectionProvider.java
public class MultiTenantContextConnectionProvider extends AbstractMultiTenantConnectionProvider {
// Do I need this and its configuratrion?
//private C3P0ConnectionProvider connectionProvider = null;
@Override
public ConnectionProvider getAnyConnectionProvider() {
// the main question is here.
}
@Override
public ConnectionProvider selectConnectionProvider(String tenantIdentifier) {
// and of course here.
}
}
Изменить
Относительно ответа @ben75:
Это новая реализация MultiTenantContextConnectionProvider
. Он больше не расширяется AbstractMultiTenantConnectionProvider
. Он скорее реализует MultiTenantConnectionProvider
, чтобы иметь возможность возвращать [Connection][4]
вместо [ConnectionProvider][5]
public class MultiTenantContextConnectionProvider implements MultiTenantConnectionProvider, ServiceRegistryAwareService {
private DataSource lazyDatasource;;
@Override
public void injectServices(ServiceRegistryImplementor serviceRegistry) {
Map lSettings = serviceRegistry.getService(ConfigurationService.class).getSettings();
lazyDatasource = (DataSource) lSettings.get( Environment.DATASOURCE );
}
@Override
public Connection getAnyConnection() throws SQLException {
return lazyDatasource.getConnection();
}
@Override
public Connection getConnection(String tenantIdentifier) throws SQLException {
final Connection connection = getAnyConnection();
try {
connection.createStatement().execute("SET SCHEMA '" + tenantIdentifier + "'");
}
catch (SQLException e) {
throw new HibernateException("Could not alter JDBC connection to specified schema [" + tenantIdentifier + "]", e);
}
return connection;
}
}