Динамическое изменение динамических переменных Hibernate
Я знаю, что есть похожие вопросы по этому сценарию, однако ни один из них, который я нашел, не соответствует моему делу, и я хотел бы иметь решение, которое не влияет на производительность. Я должен выполнять несколько соединений с различными базами данных (все postgresql), и проблема в том, что баз данных может быть много, поскольку они постоянно создаются.
В настоящий момент у меня будет только одна известная база данных, которая будет использоваться для хранения строк соединения из других баз данных. Эти базы данных могут быть 1, 2, 5, 10 или N, сложная часть заключается в том, что с моего конца я никогда не узнаю, сколько они будут, и каково их местоположение и учетные данные (все они хранятся в моей центральной БД). Вариант использования работает таким образом, что для выполнения операции в одной из этих баз данных я должен сначала извлечь из центральной базы данных место для необходимой нам БД, а затем выполнить операцию.
На данный момент я смог выполнить эту операцию, спустив SessionFactory, но операция слишком медленная даже для простого выбора/обновления, и моя забота заключается в том, что при выполнении нескольких запросов мы можем перейти из Hibernate и Исключение из памяти.
Любые идеи о том, какой был бы лучший подход для этого случая?
Ответы
Ответ 1
По моему опыту я работал со многими схемами из одной базы данных.
Hibernate необходимо создать много EntityManagerFactory для каждой отдельной схемы, а также для каждой базы данных.
Вам нужна одна EntityManagerFactory для каждой схемы или каждой базы данных, в которой вы работаете.
И вы знаете, что EntityManagerFactory очень дорог с точки зрения ресурсов и времени.
После этого получить один EntityManager очень дешево.
Итак, в вашем случае вы должны создать N EntityManagerFactory, один из них для каждой другой базы данных или другой схемы из тех же баз данных.
Поскольку создание EntityManagerFactory очень дорого, вы должны создать их только в случае необходимости и когда это необходимо, и вы знаете, что вы должны подождать почти 30 секунд или более, чтобы получить от них все.
Чтобы избежать исключения из памяти, вы можете попробовать протестировать создание от 1 до N максимального количества EntityManagerFactory и посмотреть, смогут ли ваши ресурсы поддерживать это.
Если вы видите, что, когда вы приходите к номеру X, и это всегда приводит к сбою системы, поэтому вы можете ограничить одновременное количество EntityManagerFactory этим лимитированным номером X.
Попробуйте и дайте мне знать ваши результаты или вам нужен пример кода
Ответ 2
Я думал о проблеме немного по-другому.
В соответствии с моим пониманием
Ваше требование - извлекать данные из разных баз данных, даже вы не знаете на момент разработки.
Итак, , почему вы пытаетесь установить всю эту нагрузку на hibernate для управления соединениями с таким количеством баз данных.
Вы хорошо знаете основную базу данных.
Пусть основная база данных делает все остальное.
Вы должны общаться только с базой данных и всей нагрузкой для извлечения данные из остальной базы данных должны храниться в основной базе данных.
Создайте DBLinks для разных баз данных в основной базе данных.
И поддерживать требуемые метаданные, а также в основной базе данных.
Всякий раз, когда вам нужно извлекать данные из любой недавно добавленной базы данных или так, просто спросил из основной базы данных.
Проблемы, которые могут быть решены с помощью DBLinks
- Вам не нужно выставлять учетные данные базы данных (разных баз данных) в любой таблице
- Спящий режим будет сохранен в режиме взвешивания
- Ваш код Java будет сохранен.
- Любые изменения, внесенные в любую базу данных (структура, учетные данные), будут отображаться немедленно (в другом подходе вам необходимо перезапустить приложение после любых таких изменений в базе данных).
Ссылка для DBLink в postgres
Ответ 3
У нас есть похожие вещи:
1..N в качестве разных клиентов. Каждый клиент имеет одну и ту же схему, поэтому у нас есть только 1 менеджер объектов.
Итак, вам нужно предоставить hibernete через класс реализации spi 2 и передать через свойства:
hibernate.multi_tenant_connection_provider
org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider
и
hibernate.tenant_identifier_resolver
org.hibernate.context.spi.CurrentTenantIdentifierResolver
"hibernate.multiTenancy", "SCHEMA"
Вот пример, как это сделать с spring framework
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setJpaVendorAdapter(jpaVendorAdapter());
emf.setPersistenceUnitName("security");
Properties hibernateProperties = new Properties();
hibernateProperties.put("hibernate.cache.use_second_level_cache", "true");
hibernateProperties.put("hibernate.multiTenancy", "SCHEMA");
// do not load all metadata from standard db speadup startup
hibernateProperties.put("hibernate.temp.use_jdbc_metadata_defaults", "false");
hibernateProperties.put("hibernate.dialect", "org.hibernate.dialect.PostgreSQL9Dialect");
hibernateProperties.put("hibernate.multi_tenant_connection_provider", multiTenantConnectionProvider());
hibernateProperties.put("hibernate.tenant_identifier_resolver", currentTenantIdentifierResolver(tenant));
hibernateProperties.put("hibernate.show_sql", true);
emf.setJpaProperties(hibernateProperties);
emf.setJpaDialect(new HibernateJpaDialect());
LOG.info("LocalContainerEntityManagerFactoryBean bean created");
return emf;