Необходимо настроить мой JPA-слой для использования TransactionManager (Spring Cloud Task + Batch неожиданно регистрирует PlatformTransactionManager) - PullRequest
0 голосов
/ 07 марта 2019

Я использую Spring Cloud Task + Batch в проекте.Я планирую использовать разные источники данных для бизнес-данных и данных аудита Spring для этой задачи.Поэтому я настроил что-то вроде:

   @Bean
   public TaskConfigurer taskConfigurer() {
       return new DefaultTaskConfigurer(this.singletonNotExposedSpringDatasource());
   }

   @Bean
   public BatchConfigurer batchConfigurer() {
       return new DefaultBatchConfigurer(this.singletonNotExposedSpringDatasource());
   }

, тогда как основной источник данных автоматически конфигурируется через JpaBaseConfiguration.

Проблема возникает, когда SimpleBatchConfiguration + DefaultBatchConfigurer предоставляет объект PlatformTransactionManager, так какJpaBaseConfiguration имеет @ConditionalOnMissingBean на PlatformTransactionManager.Следовательно, Batch's PlatformTransactionManager, привязанный к spring.datasource, имеет место.

Пока, похоже, это вызвано тем, что эта ошибка

Поэтому я попытался эмулировать то, что JpaBaseConfiguration определяет мой собственный PlatformTransactionManager для моего источника данных / entityManager biz.

    @Primary
    @Bean
    public PlatformTransactionManager appTransactionManager(final LocalContainerEntityManagerFactoryBean appEntityManager) {
        JpaTransactionManager transactionManager = new JpaTransactionManager();
        transactionManager.setEntityManagerFactory(appEntityManager.getObject());
        this.appTransactionManager = transactionManager;
        return transactionManager;
    }

Примечание. Я должен определить его с именем, отличным от transactionManager, в противном случае Spring находит 2 компонента и жалуется(независимо от @Primary!)

Но теперь это самое забавное.При выполнении тестов все работает гладко, тесты заканчиваются и DDLs правильно создаются как для бизнес-баз данных, так и для Batch/Task's баз данных, чтение базы данных работает безупречно, но бизнес-данные не сохраняются в моей тестовой базе данных, поэтому окончательный assertThats завершается неудачно, когдасчитая.Если я @Autowire в моем тесте PlatformTransactionManager или ÈntityManager, все указывает на то, что они правильные.Но если я отлаживаю в entityRepository.save и выполняю org.springframework.transaction.interceptor.TransactionAspectSupport.currentTransactionStatus(), кажется, что конфигурация DatasourceTransactionManager из Batch's переопределяет, так что мой пользовательский PlatformTransactionManager не используется.

Так что я думаюне проблема в том, что мой PlatformManager является основным, но что-то настраивает мой слой JPA TransactionInterceptor для использования неосновного, но transactionManager именованного bean-компонента Batch.

Я также пытался сделать свой @Configuration реализовать TransactionManagementConfigurer и переопределить PlatformTransactionManager annotationDrivenTransactionManager(), но все равно не повезло

Таким образом, я предполагаю, что я спрашиваю, есть ли способ настроить основной TransactionManager для уровня JPA.

1 Ответ

1 голос
/ 08 марта 2019

Проблема возникает, когда SimpleBatchConfiguration + DefaultBatchConfigurer представляет компонент Bean PlatformTransactionManager,

Как вы упоминали, это действительно то, что сообщалось в BATCH-2788 .Решение, которое мы исследуем, состоит в том, чтобы предоставить компонент управления транзакциями , только если Spring Batch его создает.

Тем временем вы можете установить свойство spring.main.allow-bean-definition-overriding=true, чтобы разрешить переопределение определения компонента, и установитьменеджер транзакций, который вы хотите использовать в Spring Batch с BatchConfigurer#getTransactionManager.В вашем случае это будет что-то вроде:

@Bean
public BatchConfigurer batchConfigurer() {
    return new DefaultBatchConfigurer(this.singletonNotExposedSpringDatasource()) {
        @Override
        public PlatformTransactionManager getTransactionManager() {
            return new MyTransactionManager();
        }
    };
}

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

...