Пакет Jpa Spring Boot - CannotCreateTransactionException - PullRequest
0 голосов
/ 04 мая 2018

У меня есть проект Spring Boot + JPA + Spring (+ интеграция Spring). Также есть Flyway, настроенный отдельно. Я настроил Spring Batch для использования источника данных, отличного от «spring.jpa.datasource» по умолчанию. Это отлично. Внутри моего тасклета я запрашиваю два источника данных, первый запрос на ds1 идет правильно, второй запрос на ds2 идет неправильно:

org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is java.lang.IllegalStateException: Already value [org.springframework.jdbc.datasource.ConnectionHolder@2fb082ff] for key [HikariDataSource (HikariPool-1)] bound to thread [main]

Подробнее: У меня есть класс конфигурации для каждого источника данных, помеченный

@Configuration 
@EnableTransactionManagement
@EnableJpaRepositories

В каждой конфигурации определяется bean-компонент для DataSource, LocalContainerEntityManagerFactoryBean и JpaTransactionManager с произвольным именем.

Служба определяется для каждого источника данных как:

 @Service @Transactional(transactionManager=JpaApsConfiguration.APS_TRANSACTION_MANAGER, propagation = Propagation.REQUIRES_NEW)

и диспетчер сущностей автоматически подключается с использованием правильного квалификатора (примечание: запрос сделан через классы JpaRepository)

Есть какие-нибудь предположения о том, что может вызвать такое поведение? Спасибо

Примечание:

  • База данных успешно подключается
  • У меня раньше была другая ошибка (уже исправлено, но может быть полезно): NoUniqueBeanDefinitionException, так как Spring не может определить правильный 'PlatformTransactionManager' между моими двумя транзакциями Диспетчер бинов и транзакция по умолчанию. Менеджер.

EDIT:

Вот полная трассировка стека для ошибки:

2018-05-08 12:12:24 INFO o.s.batch.core.job.SimpleStepHandler - Выполнение шага: [STEP # PROCESS_SHIPMENTS] 2018-05-08 12:12:24 ОШИБКА o.s.batch.core.step.AbstractStep - Обнаружена ошибка при выполнении шага STEP # PROCESS_SHIPMENTS в задании PROCESS_APS org.springframework.transaction.CannotCreateTransactionException: не удалось открыть JPA EntityManager для транзакции; Вложенное исключение - java.lang.IllegalStateException: значение уже [org.springframework.jdbc.datasource.ConnectionHolder@351e89fc] для ключа [HikariDataSource (HikariPool-1)], связанного с потоком [main] в org.springframework.orm.jpa.JpaTransactionManager.doBegin (JpaTransactionManager.java:450) в org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction (AbstractPlatformTransactionManager.java:378) в org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNeeded (TransactionAspectSupport.java:474) в org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction (TransactionAspectSupport.java:289) в org.springframework.transaction.interceptor.TransactionInterceptor.invoke (TransactionInterceptor.java:98) в org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:185) в org.springframework.aop.framework.CglibAopProxy $ DynamicAdvisedInterceptor.intercept (CglibAopProxy.java:689) at dkr.astreconnector.service.GespeService $$ EnhancerBySpringCGLIB $$ 73dbb368.getValueDetailByUniq () в dkr.astreconnector.batch.worker.ShipmentProcessor.process (ShipmentProcessor.java:63) в dkr.astreconnector.batch.worker.ShipmentProcessor.process (ShipmentProcessor.java:30) в org.springframework.batch.core.step.item.SimpleChunkProcessor.doProcess (SimpleChunkProcessor.java:126) в org.springframework.batch.core.step.item.SimpleChunkProcessor.transform (SimpleChunkProcessor.java:303) в org.springframework.batch.core.step.item.SimpleChunkProcessor.process (SimpleChunkProcessor.java:202) в org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute (ChunkOrientedTasklet.java:75) в org.springframework.batch.core.step.tasklet.TaskletStep $ ChunkTransactionCallback.doInTransaction (TaskletStep.java:406) в org.springframework.batch.core.step.tasklet.TaskletStep $ ChunkTransactionCallback.doInTransaction (TaskletStep.java:330) в org.springframework.transaction.support.TransactionTemplate.execute (TransactionTemplate.java:140) в org.springframework.batch.core.step.tasklet.TaskletStep $ 2.doInChunkContext (TaskletStep.java:272)в org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration (StepContextRepeatCallback.java:81) в org.springframework.batch.repeat.support.RepeatTemplate.getNextResult (RepeatTemplate.java:375) в org.springframework.batch.repeat.support.RepeatTemplate.executeInternal (RepeatTemplate.java:215) на org.springframework.batch.repeat.support.RepeatTemplate.iterate (RepeatTemplate.java:145) в org.springframework.batch.core.step.tasklet.TaskletStep.doExecute (TaskletStep.java:257) в org.springframework.batch.core.step.AbstractStep.execute (AbstractStep.java:200) в org.springframework.batch.core.job.SimpleStepHandler.handleStep (SimpleStepHandler.java:148) в org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep (JobFlowExecutor.java:66) в org.springframework.batch.core.job.flow.support.state.StepState.handle (StepState.java:67) в org.springframework.batch.core.job.flow.support.SimpleFlow.resume (SimpleFlow.java:169) в org.springframework.batch.core.job.flow.support.SimpleFlow.start (SimpleFlow.java:144) в org.springframework.batch.core.job.flow.FlowJob.doExecute (FlowJob.java:136) в org.springframework.batch.core.job.AbstractJob.execute (AbstractJob.java:308) в org.springframework.batch.core.launch.support.SimpleJobLauncher $ 1.run (SimpleJobLauncher.java:141) в org.springframework.core.task.SyncTaskExecutor.execute (SyncTaskExecutor.java:50) в org.springframework.batch.core.launch.support.SimpleJobLauncher.run (SimpleJobLauncher.java:134) в org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.execute (JobLauncherCommandLineRunner.java:163) в org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.executeLocalJobs (JobLauncherCommandLineRunner.java:179) в org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.launchJobFromProperties (JobLauncherCommandLineRunner.java:134) в org.springframework.boot.autoconfigure.batch.JobLauncherCommandLineRunner.run (JobLauncherCommandLineRunner.java:128) в org.springframework.boot.SpringApplication.callRunner (SpringApplication.java:790) в org.springframework.boot.SpringApplication.callRunners (SpringApplication.java:774) в org.springframework.boot.SpringApplication.run (SpringApplication.java:335) в org.springframework.boot.SpringApplication.run (SpringApplication.java:1246) в org.springframework.boot.SpringApplication.run (SpringApplication.java:1234) в dkr.astreconnector.AstreConnectorBatchApplication.main (AstreConnectorBatchApplication.java:14) Вызывается: java.lang.IllegalStateException: значение уже [org.springframework.jdbc.datasource.ConnectionHolder@351e89fc] для ключа [HikariDataSource (HikariPool-1)], связанного с потоком [main] в org.springframework.transaction.support.TransactionSynchronizationManager.bindResource (TransactionSynchronizationManager.java:193) в org.springframework.orm.jpa.JpaTransactionManager.doBegin (JpaTransactionManager.java:425) ... пропущено 43 общих кадра 2018-05-08 12:12:24 ИНФОРМАЦИЯ osbclsupport.SimpleJobLauncher - Задание: [FlowJob: [name = PROCESS_APS]] завершено со следующими параметрами: [{run.id = 128}] и следующим состоянием: [FAILED]

1 Ответ

0 голосов
/ 15 апреля 2019

Немного поздно, но я бы хотел ответить на @ mad_fox

Первичная база данных:

@Configuration
@EnableJpaRepositories(
    entityManagerFactoryRef = JpaAppsConfiguration.APPS_ENTITY_MANAGER,
    transactionManagerRef = "transactionManager",
    basePackages = { JpaAppsConfiguration.APPS_REPOSITORIES })
@EnableAutoConfiguration
public class JpaAppsConfiguration {

public final static String APPS_PERSISTENCE_UNIT = "apps";
public final static String APPS_DATA_SOURCE = "appDs";
public final static String APPS_ENTITY_MANAGER = "appsEmf";
public final static String APPS_TRANSACTION_MANAGER = "appsTm";
protected final static String APPS_PACKAGES = ""; //my models package
protected final static String APPS_REPOSITORIES = ""; //my repos package

@Primary
@Bean(name = APPS_DATA_SOURCE)
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource appsDataSource() {
    return DataSourceBuilder.create().build();
}

@Primary
@Bean(name = APPS_ENTITY_MANAGER)
@PersistenceContext(unitName = APPS_PERSISTENCE_UNIT)
public LocalContainerEntityManagerFactoryBean appsEntityManagerFactory(EntityManagerFactoryBuilder builder,
        @Qualifier(APPS_DATA_SOURCE) DataSource appsDataSource) {
    LocalContainerEntityManagerFactoryBean emf = builder
            .dataSource(appsDataSource)
            .persistenceUnit(APPS_PERSISTENCE_UNIT)
            .packages(APPS_PACKAGES)
            .build();

    // Vendor adapter
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    emf.setJpaVendorAdapter(vendorAdapter);
    return emf;
}
}

Вторичный дБ:

@Configuration
@EnableJpaRepositories(
    entityManagerFactoryRef = JpaGepeConfiguration.GEPE_ENTITY_MANAGER, 
    basePackages = { JpaGepeConfiguration.GEPE_REPOSITORIES })
@EnableAutoConfiguration
public class JpaGepeConfiguration {

public static final String GEPE_PERSISTENCE_UNIT = "gn1";
public static final String GEPE_DATA_SOURCE = "gn1ds";
public static final String GEPE_ENTITY_MANAGER = "gn1emf";
public static final String GEPE_TRANSACTION_MANAGER = "gn1tm";
public static final String GEPE_PACKAGES = ""; //my models package
public static final String GEPE_REPOSITORIES = ""; //my repos package

@Bean(name = GEPE_DATA_SOURCE)
@ConfigurationProperties(prefix = "gn1.datasource")
public DataSource gepeDataSource() {
    return DataSourceBuilder.create().build();
}

@Bean(name = GEPE_ENTITY_MANAGER)
@PersistenceContext(unitName = GEPE_PERSISTENCE_UNIT)
public LocalContainerEntityManagerFactoryBean gepeEntityManagerFactory(EntityManagerFactoryBuilder builder,
        @Qualifier(GEPE_DATA_SOURCE) DataSource gepeDataSource) {
    LocalContainerEntityManagerFactoryBean emf = builder
            .dataSource(gepeDataSource)
            .persistenceUnit(GEPE_PERSISTENCE_UNIT)
            .packages(GEPE_PACKAGES)
            .build();

    // Vendor adapter
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    emf.setJpaVendorAdapter(vendorAdapter);
    return emf;
}
}

Методы в классах @Service для первичной базы данных аннотируются как:

@Transactional(transactionManager = JpaAppsConfiguration.APPS_TRANSACTION_MANAGER, readOnly = false, propagation = Propagation.REQUIRED, noRollbackFor = Exception.class)

Параметры в файле свойств следующие:

#DATABASE CONNECTION
#Primary
spring.datasource.username=
spring.datasource.password=
spring.datasource.driverClassName=
spring.datasource.url=j
spring.datasource.jdbcUrl=
spring.datasource.name=
#Secondary
gepe.datasource.username=
gepe.datasource.password=
gepe.datasource.driverClassName=
gepe.datasource.url=
gepe.datasource.jdbcUrl=
gepe.datasource.name=

Надеюсь, это поможет.

...