Мы используем мультитенантную спящий режим Hibernate + Spring, как описано в Мультитенантность в Hibernate . Мы предоставляем MultiTenantConnectionProvider и CurrentTenantIdentifierResolver при создании менеджера сущностей (см. Пример ниже).
В нашем MultiTenantConnectionProvider целевая база данных для арендатора не настроена статически. Вместо этого он динамически определяет данные целевой базы данных текущего арендатора, вызывая другую службу, а затем создает для нее источник данных.
Теперь мы сталкиваемся с проблемой, заключающейся в том, что при запуске весеннего загрузочного сервера Hibernate вызывает метод MultiTenantConenctionProvider.getAnyConnection (). Во время запуска сервера в этом контексте нет арендатора, и, следовательно, у нас нет базы данных для создания подключения. Кроме того, у нас нет фиктивной базы данных в нашей настройке, которую мы можем использовать во время запуска сервера
- Если мы вернем null, при запуске сервера произойдет сбой с NullPointerException
- Если мы переопределим При вызове метода anyConnection () и генерации исключения (как можно видеть из кода ниже) сервер просто регистрирует исключение и продолжает запуск сервера.
При значении 2 все работает нормально, и мы способен добиться прогресса. Однако мы действительно хотим избавиться от этого ненужного исключения, которое регистрируется при каждом перезапуске сервера весенней загрузки.
Мы ищем способ отключить режим гибернации при попытке подключения к БД во время запуска сервера, особенно когда мультитенантная стратегия hibernate установлена. Это поведение несовместимо с мультитенантным программным обеспечением
Есть ли какой-либо способ, которым мы можем запретить hiberate пытаться получить соединение (т.е. сделать вызов MultiTenantConenctionProvider.getAnyConnection ()) во время запуска сервера?
Пожалуйста, сообщите
Ниже приведен пример конфигурации Spring
@Configuration
@EnableTransactionManagement
public class MultiTenantHibernateJpaConfig {
@Autowired
private JpaProperties jpaProperties;
@Bean
public MultiTenantConnectionProvider multiTenantConnectionProvider() {
return new MultiTenantConnectionProviderImpl();
}
@Bean
public CurrentTenantIdentifierResolver currentTenantIdentifierResolver() {
return new CurrentTenantIdentifierResolverImpl();
}
@Value("${jpaconfig.packages-to-scan:#{null}}")
private String packagesToScan;
@Bean
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactory(MultiTenantConnectionProvider multiTenantConnectionProvider,
CurrentTenantIdentifierResolver currentTenantIdentifierResolver) {
Map<String, Object> hibernateProps = new LinkedHashMap<>();
hibernateProps.put(Environment.MULTI_TENANT, MultiTenancyStrategy.SCHEMA);
hibernateProps.put(Environment.MULTI_TENANT_CONNECTION_PROVIDER, multiTenantConnectionProvider);
hibernateProps.put(Environment.MULTI_TENANT_IDENTIFIER_RESOLVER, currentTenantIdentifierResolver);
hibernateProps.put("javax.persistence.schema-generation.database.action", "none");
hibernateProps.put("javax.persistence.query.timeout", "5");
hibernateProps.put(Environment.DIALECT, "org.hibernate.dialect.Oracle10gDialect");
hibernateProps.putAll(this.jpaProperties.getProperties());
LocalContainerEntityManagerFactoryBean result = new LocalContainerEntityManagerFactoryBean();
if(packagesToScan != null) {
//handle multiple packages separated by comma
result.setPackagesToScan(packagesToScan.split("\\s*,\\s*"));
}
result.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
result.setJpaPropertyMap(hibernateProps);
return result;
}
Ниже приведена реализация MultiTenantConnectionProvider
public class MultiTenantConnectionProviderImpl extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl {
private static final long serialVersionUID = 1L;
public MultiTenantConnectionProviderImpl()
{
}
@Override
protected DataSource selectAnyDataSource()
{
return null;
}
@Override
protected DataSource selectDataSource(String tenantIdentifier) {
//This in turn makes a call to a remote service to fetch current tenant
//database details and then creates a datasource for it.
return DataSourceManager.getDataSource(tenantIdentifier);
}
@Override
public Connection getAnyConnection() throws SQLException{
//Called during server startup. Cannot do any thing as tenant is not known
// and there is no default datasource
throw new SQLException("not implemented in multi-tenant environment");
}
@Override
public void releaseAnyConnection(Connection connection) throws SQLException
{
//Called during server startup. Cannot do any thing as tenant is not known
// and there is no default datasource
throw new SQLException("not implemented in multi-tenant environment");
}
}