Укажите hibernate.multi_tenant_connection_provider без использования отражения

#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 .