powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Hibernate: два источника данных в одном контексте
12 сообщений из 12, страница 1 из 1
Hibernate: два источника данных в одном контексте
    #39645857
fplab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброго утра всем!
Никогда раньше такого не делал и не могу понять где рыть землю.
Есть две БД PostgreSQL: master и slave. Структуры полностью идентичны. Базы располагаются на разных серверах и не в локальной сети. Надо сделать программную перекачку данных из таблицы на master в аналогичную таблицу на slave.
Используется Spring+Hibernate.
В одном контексте описаны два источника (соотв.для master и slave):
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
    <context:component-scan base-package="com.bureau"/>
    <context:property-placeholder location="classpath:META-INF/rdbs.properties"/>

    <bean id="domainDao" class="com.bureau.impl.DomainDaoImpl"/>

    <!-- HikariCP configuration for master-node -->
    <bean id="hikariConfigMaster" class="com.zaxxer.hikari.HikariConfig">
        <property name="poolName" value="springHikariCPMaster"/>
        <property name="maximumPoolSize" value="${hikariMaster.maximumPoolSize}"/>
        <property name="maxLifetime" value="${hikariMaster.maxLifetime}"/>
        <property name="idleTimeout" value="${hikariMaster.idleTimeout}"/>
        <property name="dataSourceClassName" value="${hikariMaster.driverName}"/>
        <property name="dataSourceProperties">
            <props>
                <prop key="serverName">${hikariMaster.serverName}</prop>
                <prop key="portNumber">${hikariMaster.portNumber}</prop>
                <prop key="databaseName">${hikariMaster.databaseName}</prop>
                <prop key="user">${hikariMaster.user}</prop>
                <prop key="password">${hikariMaster.password}</prop>
            </props>
        </property>
    </bean>

    <!-- HikariCP configuration for slave-node -->
    <bean id="hikariConfigSlave" class="com.zaxxer.hikari.HikariConfig">
        <property name="poolName" value="springHikariCPSlave"/>
        <property name="maximumPoolSize" value="${hikariSlave.maximumPoolSize}"/>
        <property name="maxLifetime" value="${hikariSlave.maxLifetime}"/>
        <property name="idleTimeout" value="${hikariSlave.idleTimeout}"/>
        <property name="dataSourceClassName" value="${hikariSlave.driverName}"/>
        <property name="dataSourceProperties">
            <props>
                <prop key="serverName">${hikariSlave.serverName}</prop>
                <prop key="portNumber">${hikariSlave.portNumber}</prop>
                <prop key="databaseName">${hikariSlave.databaseName}</prop>
                <prop key="user">${hikariSlave.user}</prop>
                <prop key="password">${hikariSlave.password}</prop>
            </props>
        </property>
    </bean>

    <!-- Data source for master-node -->
    <bean id="dataSourceMaster" class="com.zaxxer.hikari.HikariDataSource">
        <constructor-arg ref="hikariConfigMaster"/>
    </bean>

    <!-- Data source for slave-node -->
    <bean id="dataSourceSlave" class="com.zaxxer.hikari.HikariDataSource">
        <constructor-arg ref="hikariConfigSlave"/>
    </bean>

    <!-- Entity manager factory for master-node -->
    <bean id="emfMaster" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSourceMaster"/>
        <property name="packagesToScan" value="com.bureau.domain.master"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="generateDdl" value="false"/>
            </bean>
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL94Dialect</prop>
                <prop key="hibernate.max_fetch_depth">3</prop>
                <prop key="hibernate.jdbc.fetch_size">50</prop>
                <prop key="hibernate.jdbc.batch_size">10</prop>
                <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
                <prop key="hibernate.format_sql">true</prop>
            </props>
        </property>
    </bean>

    <!-- Entity manager factory for slave-node -->
    <bean id="emfSlave" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSourceSlave"/>
        <property name="packagesToScan" value="com.bureau.domain.slave"/>
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="generateDdl" value="false"/>
            </bean>
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQL94Dialect</prop>
                <prop key="hibernate.max_fetch_depth">3</prop>
                <prop key="hibernate.jdbc.fetch_size">50</prop>
                <prop key="hibernate.jdbc.batch_size">10</prop>
                <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
                <prop key="hibernate.format_sql">true</prop>
            </props>
        </property>
    </bean>



Собственно, сама реализация (там всего три метода):
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
@Service("domainDao")
@Repository
@Transactional
public class DomainDaoImpl implements DomainDao {
    private static final Logger LOG = LoggerFactory.getLogger("DomainDaoImpl.class");

    @Value("${sql.limit}")
    private int limit;

    // Менеджеры сущностей
    @PersistenceContext(unitName = "emfMaster")
    private EntityManager entityManagerMaster;
    @PersistenceContext(unitName = "emfSlave")
    private EntityManager entityManagerSlave;

    @Transactional(readOnly=true)
    @Override
    public List<MessagesMaster> findUnreplicatedRows(long id) {
        LOG.info("[RDBS] findUnreplicatedRows: {}, {}", id, limit);
        TypedQuery<MessagesMaster> query = entityManagerMaster.createNamedQuery("master.findUnreplicatedRows", MessagesMaster.class);
        query.setParameter("id", id);
        query.setMaxResults(limit);

        return query.getResultList();
    }

    @Transactional(readOnly=true)
    @Override
    public Long findMasterMaxId() {
        LOG.info("[RDBS] findMasterMaxId");
        Query query = entityManagerMaster.createNamedQuery("master.findMasterMaxId", Long.class);

        return (long)query.getSingleResult();
    }

    @Transactional(readOnly=true)
    @Override
    public Long findSlaveMaxId() {
        LOG.info("[RDBS] findSlaveMaxId");
        Query query = entityManagerSlave.createNamedQuery("slave.findSlaveMaxId", Long.class);

        return (long)query.getSingleResult();
    }
}


Пытаюсь загрузить контекст
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
    private DomainDao domainDao;

    public Main() {
        GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
        ctx.load("classpath:META-INF/rdbs-context.xml");
        ctx.refresh();

        domainDao = ctx.getBean("domainDao", DomainDao.class);
    }


и получаю "бяку":
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
2018-05-17 08:11:19,083 INFO  HikariDataSource:70 - springHikariCPMaster - Started.
2018-05-17 08:11:19,218 INFO  PoolBase:444 - springHikariCPMaster - Driver does not support get/set network timeout for connections. (Method org.postgresql.jdbc42.Jdbc42Connection.getNetworkTimeout() is not yet implemented.)
2018-05-17 08:11:19,342 INFO  LocalContainerEntityManagerFactoryBean:336 - Building JPA container EntityManagerFactory for persistence unit 'default'
2018-05-17 08:11:19,358 INFO  LogHelper:31 - HHH000204: Processing PersistenceUnitInfo [
	name: default
	...]
2018-05-17 08:11:19,418 INFO  Version:37 - HHH000412: Hibernate Core {5.1.0.Final}
2018-05-17 08:11:19,419 INFO  Environment:213 - HHH000206: hibernate.properties not found
2018-05-17 08:11:19,420 INFO  Environment:317 - HHH000021: Bytecode provider name : javassist
2018-05-17 08:11:19,452 INFO  Version:66 - HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
2018-05-17 08:11:19,470 WARN  GenericXmlApplicationContext:546 - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'emfMaster' defined in class path resource [META-INF/rdbs-context.xml]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: javassist/bytecode/ClassFile
2018-05-17 08:11:19,470 INFO  HikariPool:214 - springHikariCPMaster - Close initiated...
2018-05-17 08:11:19,513 INFO  HikariPool:254 - springHikariCPMaster - Closed.
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'emfMaster' defined in class path resource [META-INF/rdbs-context.xml]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: javassist/bytecode/ClassFile
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1582)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1054)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:829)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538)
	at com.bureau.Main.<init>(Main.java:13)
	at com.bureau.Main.main(Main.java:19)


Буду признателен за подсказку - где косяк и куда смотреть
...
Рейтинг: 0 / 0
Hibernate: два источника данных в одном контексте
    #39645873
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fplab,
Куда вы только хибер не суете.
Код: java
1.
pg_dump -t table_to_copy source_db | psql target_db


Иди на форум базы
...
Рейтинг: 0 / 0
Hibernate: два источника данных в одном контексте
    #39645879
fplab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123,
Спасибо, но увы :( Об этом способе я, конечно, извещен :)
Нужен программный способ. Данные постоянно льются в master. Таблицу в slave надо постоянно пополнять данными, пришедшими в master. Такие утилиты как slony не подходят (во всяком случае у меня нет возможности его установить и настроить). Так что остается только программный способ
...
Рейтинг: 0 / 0
Hibernate: два источника данных в одном контексте
    #39645908
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fplab,
Ты так обосновал, как будто все прогеры на ветке субд делают через хибер.
Я просто сомневаюсь, что ОРМ умеет держать сессию и маппить на две удаленные базы.
DBLink еще есть. Все юзают кроме тебя как белой вороны.
Imho
...
Рейтинг: 0 / 0
Hibernate: два источника данных в одном контексте
    #39645909
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fplabтолько программный способ
JDBC можно поискать и взять сразу строку-запись чтобы вставить в JDBC2.
...
Рейтинг: 0 / 0
Hibernate: два источника данных в одном контексте
    #39645916
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fplabНадо сделать программную перекачку данных из таблицы на master в аналогичную таблицу на slave.
Если вы собрались это делать на Hibernate, то это как на камазе ездить в магазин за продуктами. ORM для этого совершенно не приспособлен и не предназначен.

При этом задача является инфраструктурной. Но вы зачем-то мешаете её в свою бизнес-логику.

Прежде чем приступать к реализации, стоит обдумать как это вообще всё должно работать
- Как обрабатывать транзакцию и ошибки?
- Как бороться с дикими блокирующими задержками связанным с удаленностью БД?
- Как синхронизировать генерируемые значения?
- Как обрабатывать ситуации когда нужно "руками" накатывать исправление в БД?
- Почему базы две а Java сервер один?
И много всего такого. За 15 лет я видел не мало попыток написать репликацию БД на коленке, но при этом ни одна из них не была успешной.

Единственным относительно рабочим решением была репликация целиком запросов к сервисам и асинхронное выполение целых бизнес-транзакций на отдельных серверах. Но там была своя специфика репликации данных между офисами. А мы даже не знаем с какой целью вы делаете то что делаете.

И, да, вам точно в другую ветку форума.
...
Рейтинг: 0 / 0
Hibernate: два источника данных в одном контексте
    #39645920
Локшин Марк
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123DBLink еще есть. Все юзают кроме тебя как белой вороны.

Лучше FDW, на него даже hibernate можно натянуть, т.к. выглядить это будет как еще одна схема с такой же структурой как в локальной БД.
...
Рейтинг: 0 / 0
Hibernate: два источника данных в одном контексте
    #39645980
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Локшин Маркдаже hibernate можно натянуть,если цель натянуть, сову на глобус, то не ко мне. Я и в sql тоже комфортно работаю.
...
Рейтинг: 0 / 0
Hibernate: два источника данных в одном контексте
    #39646232
mad_nazgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fplab,

Версия Java какая? :-)
...
Рейтинг: 0 / 0
Hibernate: два источника данных в одном контексте
    #39646234
fplab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Petro123fplab,
Ты так обосновал, как будто все прогеры на ветке субд делают через хибер.
Я просто сомневаюсь, что ОРМ умеет держать сессию и маппить на две удаленные базы.
DBLink еще есть. Все юзают кроме тебя как белой вороны.
Imho

Я ничего не обосновывал. Есть задача. Глуповатая согласен, но ее надо решать. И именно программным способом, увы. Заказчик далеко, согласовать что-либо - тяжко. Время идет. А данные в slave нужны (с ними работает другая группа разработчиков).
На самом деле не я один столкнулся с такой задачей (например, см.
тут или и тут , а также довольно много других).
Сделал и спасибо всем (хотя и совсем не так, как в приведенных ссылках).
...
Рейтинг: 0 / 0
Hibernate: два источника данных в одном контексте
    #39646235
fplab
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mad_nazgul,
1.8
...
Рейтинг: 0 / 0
Hibernate: два источника данных в одном контексте
    #39646580
mad_nazgul
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fplabmad_nazgul,
1.8

Тады ОЙ.
Я делал что-то подобное, но на spring-boot, Java 1.8.

Настройку EntityManager делал в классах конфигурации.
Например
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Hibernate: два источника данных в одном контексте
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]