У меня задача, читать в одной базе данных (db2), а писать в другую (oracle).
spring boot jpa, hibernate
Я сконфигурировал у себя два Datasource, два EntityManagerFactory, два PlatformTransactionManager. Под каждую базу.
У меня так же под вторую базу данных есть набор Entity классов и к каждому у меня есть свой Repository extends JpaRepository.
Собственно сетап работает. Так как приложение наверняка может читать в базе - источнике данных и апдейтить там данные jdbcTemplate компонентой. В другой базе - куда надо писать, приложение тоже может читать. Я в трейсах вижу запросы к базе (к примеру что бы посчитать количество записей в табличке) метода findById репозитория.
Но потом начинается какая то фигня, при попытке писать через репозитории. Вызвается метод save(entity) я в логе hibernate вижу, что сущность добавлена в очередь.
22-01-21 Fr 20:15:16.830 DEBUG [actSaveEventListener] : Generated identifier: component[]{}, using strategy: org.hibernate.id.CompositeNestedGeneratedValueGenerator
22-01-21 Fr 20:15:16.830 TRACE [actSaveEventListener] : Saving [com.batch.vamos2dwh.writer.persistence.dwh.model.StF...
22-01-21 Fr 20:15:16.830 TRACE [ActionQueue ] : Adding an EntityInsertAction for [com.batch.vamos2dwh.writer.persistence.dwh.model.StF...] object
22-01-21 Fr 20:15:16.830 TRACE [ActionQueue ] : Adding insert with no non-nullable, transient entities: [EntityInsertAction[com.batch.vamos2dwh.writer.persistence.dwh.model.StF...]
22-01-21 Fr 20:15:16.830 TRACE [ActionQueue ] : Adding resolved non-early insert action.
Но почему то сущность в итоге не пишется в базу данных. Я не вижу даже insert-ов в логе.
Я думаю у меня какая то фигня с транзакциями.
Я настроил ChainedTransactionManager, что бы коммитить сразу в обоих базах, при успехе. Но коммитится только в одной, в источнике.
@Bean(name = "chainedTransactionManager")
public ChainedTransactionManager transactionManager(@Qualifier("dwhTransactionManager") PlatformTransactionManager ds1,
@Qualifier("vamosTransactionManager") PlatformTransactionManager ds2) {
return new ChainedTransactionManager(ds1, ds2);
}
И использую его в самой первой точке входа компоненты, которая потом все это делает.
@Transactional(value="chainedTransactionManager", propagation = Propagation.REQUIRES_NEW)
public int processSCFZ() {
Больше у меня transactional нигде нету, и метод processSCFZ вызвается из другогой компоненты. Связанны по @Autowired, то -есть транзакция должна создаваться.
Я почему грешу на транзакции, потому что я вижу, в логе для каждого save
getting transaction for blablaEntityRepository.save
Это вроде не нормально.
Почему такое может происходить? Как то можно включить трассировку этих транзакций, что бы понять, почему она не создается. А то уже все отмечают пятницу, а я так и не смог записать в базу. Причем когда все это читало данные не из другой базы данных, а из MQ, все работало и писало в базу как надо. Сломалось после того как добавил вторую базу источником.
Вот конфигурация целевой базы, которая не хочет писать данные. Другая сконфигурирована аналогично, только другой префикс
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "com.batch.vamos2dwh.writer.persistence.dwh.repository",
entityManagerFactoryRef = "dwhEntityManagerFactory",
transactionManagerRef = "dwhTransactionManager")
public class DwhDatasourceConfiguration {
@Value("${dwh.jpa.properties.hibernate.dialect}")
private String hibernateDialect;
@Bean(name = "dwhDatasource")
@ConfigurationProperties(prefix = "dwh.datasource")
@Primary
public DataSource dwhDatasource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "dwhTransactionManager")
@Primary
public PlatformTransactionManager dwhTransactionManager(@Qualifier("dwhDatasource") DataSource ds) {
return new DataSourceTransactionManager(ds);
}
@Bean(name = "dwhJdbc")
public JdbcTemplate vamosJdbc(@Qualifier("dwhDatasource") DataSource ds) {
return new JdbcTemplate(ds);
}
@Bean(name = "dwhEntityManagerFactory")
@Primary
public LocalContainerEntityManagerFactoryBean dwhEntityManagerFactory(
EntityManagerFactoryBuilder entityManagerFactoryBuilder,
@Qualifier("dwhDatasource") DataSource dwhDatasource) {
HashMap<String, Object> props = new HashMap<>();
props.put("hibernate.dialect", hibernateDialect);
return entityManagerFactoryBuilder
.dataSource(dwhDatasource)
.properties(props)
.packages("com.batch.vamos2dwh.writer.persistence.dwh")
.persistenceUnit("dwhPersistence")
.build();
}
}