Я пытаюсь настроить многопользовательское веб-приложение с (в идеале) возможностью одновременного использования как подхода, разделенного базой данных, так и подхода, разделенного схемой. Хотя я собираюсь начать с разделения схем. В настоящее время мы используем:
- Весна 4.0.0
- Спящий режим 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) Является ли это правильным путем для будущей реализации разделения базы данных и схемы?
Любые комментарии или описания приветствуются.
application-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;
}
}
LazyConnectionDataSourceProxy
(один c3p0) через конфигурацию xml. 2) Сделать конкретную реализациюMultiTenantConnectionProvider
также реализуетServiceRegistryAwareService
3) Использовать источник данных в MultiTenantConnectionProvider. он жеdatasource.getConnection()
. Это приемлемо? 29.01.2014