#java #hibernate #multi-tenant #dropwizard
Вопрос:
В настоящее время я указываю поставщика многопользовательских подключений hibernate и распознаватель в файле свойств, используя это.
hibernate.multi_tenant_connection_provider: com.app.MapMultiTenantConnectionProvider
hibernate.tenant_identifier_resolver: com.app.MultiTenantCurrentTenantIdentifierResolver
Hibernate использует отражение для загрузки этих классов. Проблема в том, что мне нужны эти классы для доступа к определенным переменным. Например, Файл конфигурации DropWizard и организация пользователей должны знать URL-адрес базы данных и идентификатор клиента. В настоящее время мне приходится делать переменные статическими, чтобы поставщик имел к ним доступ.
В таких учебниках есть вся необходимая информация, указанная в файле свойств, в то время как мне нужно, чтобы моя была динамичной в зависимости от текущего подключенного пользователя.
Вот пример того, что мне приходится делать со статическими переменными. В целом это делает код довольно запутанным.
public class MapMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider {
private static Logger log = LoggerFactory.getLogger(MapMultiTenantConnectionProvider.class);
private Map<String, ConnectionProvider> connectionProviderMap = new HashMap<>();
public MapMultiTenantConnectionProvider() throws IOException {
}
@Override
protected ConnectionProvider getAnyConnectionProvider() {
return getConnectionProviderForTenant("chorus");
}
@Override
protected ConnectionProvider selectConnectionProvider(final String tenantIdentifier) {
return getConnectionProviderForTenant(tenantIdentifier);
}
private ConnectionProvider getConnectionProviderForTenant(final String tenantId) {
final ConnectionProvider connectionProvider;
if (!connectionProviderMap.containsKey(tenantId)) {
// Access a static variable here that contains the database URL, username, etc
final MyConfig config = MyApp.CONFIGURATION;
final Properties properties = new Properties();
properties.setProperty("hibernate.connection.url", config.connectionUrl);
properties.setProperty("hibernate.connection.username", config.username);
properties.setProperty("hibernate.connection.password", config.password);
properties.setProperty("hibernate.dialect", config.databaseConfig.getHibernateDialect());
final DriverManagerConnectionProviderImpl newConnectionProvider = new DriverManagerConnectionProviderImpl();
newConnectionProvider.configure(properties);
this.connectionProviderMap.put(tenantId, newConnectionProvider);
connectionProvider = newConnectionProvider;
} else {
connectionProvider = connectionProviderMap.get(tenantId);
}
return connectionProvider;
}
}
Я хотел бы создать экземпляр и передать конфигурацию (или что-нибудь еще необходимое), как это.
new MapMultiTenantConnectionProvider(configuration)
Можно ли указать поставщика, создав его экземпляр вместо определения в файле свойств?
Комментарии:
1. Попробуйте изучить
org.hibernate.service.spi.ServiceContributor
иJaccIntegrator
привести пример того, как взаимодействовать сStandardServiceRegistryBuilder
Ответ №1:
Вы можете реализовать ServiceRegistryAwareService
интерфейс для получения доступа к гибернации ServiceRegistry
, который предоставляет вам доступ практически ко всем конфигурациям гибернации. Я не знаю, как вы обычно получаете доступ к этой конфигурации dropwizard, но в случае, если она доступна через управляемый компонент, вы можете получить доступ ManagedBeanRegistry
и получить доступ к компоненту, предоставляющему эту информацию. Кроме этого, вы мало что можете сделать. Пожалуйста, обратите внимание, однако, что ваша текущая реализация не является потокобезопасной. Вы должны использовать ConcurrentHashMap
и использовать putIfAbsent
, или даже лучше computeIfAbsent
.