Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Hibernate: два источника данных в одном контексте / 12 сообщений из 12, страница 1 из 1
17.05.2018, 08:24
    #39645857
fplab
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate: два источника данных в одном контексте
Доброго утра всем!
Никогда раньше такого не делал и не могу понять где рыть землю.
Есть две БД 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
17.05.2018, 08:59
    #39645873
Petro123
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Hibernate: два источника данных в одном контексте
fplab,
Куда вы только хибер не суете.
Код: java
1.
pg_dump -t table_to_copy source_db | psql target_db


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

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

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

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

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

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

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

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

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

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


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