#java #spring-boot #hibernate #spring-batch #spring-transactions
Вопрос:
Недавно я перенес свое Java-приложение spring boot/batch из spring-boot/spring-framework (соответственно) 1.x.x/4.x.x в => 2.x.x/5.x.x (2.2.4/5.2.3, если быть точным). Проблема в том, что что-то определенно не так (на мой взгляд) с менеджером транзакций/сущностей, так как, когда .saveAll()
метод вызывается из JpaRepository
класса моего уровня сохранения базы данных, он переходит в фреймворк SpringAOP/библиотечный код и в бесконечный цикл. Я вижу, что он возвращает объект «defaulttransaction» из метода (invoke()). Мое приложение на 1.x.x/4.x.x, когда оно работало, возвращало бы фактический список ArrayList здесь моих сущностей. Я использую spring-boot-starter
, spring-boot-starter-web
, spring-boot-starter-data-jpa
, spring-boot-starter-batch
, и hibernate
/ hibernate-envers
/ hibernate-entitymanager
(также, конечно, много других зависимостей, дайте мне знать, если вы хотите, чтобы я их перечислил).
После некоторых исследований я обнаружил, что люди говорят, что @EnableBatchProcessing
в аннотации Spring Batch устанавливается менеджер транзакций по умолчанию, что, если я использую JPA, может вызвать проблемы. Ссылка: https://github.com/spring-projects/spring-boot/issues/2363
уилкинсона предложила определить этот боб в моем @Configuration
классе:
@Bean
public BatchConfigurer batchConfigurer(DataSource dataSource, EntityManagerFactory entityManagerFactory) {
return new BasicBatchConfigurer(dataSource, entityManagerFactory);
}
Я получаю ошибку, когда делаю это, потому что в нем говорится BasicBatchConfigurer()
, что доступ защищен. Каков наилучший способ создать этот экземпляр?
Я также видел, как некоторые люди говорили, что удаление @EnableBatchProcessing
аннотации устраняет проблему с сохранением базы данных, но когда я удаляю это, я теряю возможность автоматически подключать свой JobBuilderFactory и StepBuilderFactory. Есть ли способ удалить аннотацию и включить эти объекты в мой код, чтобы я мог хотя бы проверить, работает ли это? Извините, я не совсем мастер с весенней партией/весной.
В своем @Configuration
классе я использую PlatformTransactionManager
. Я создаю свою вакансию примерно так.:
@Bean
public JobRepository jobRepository(PlatformTransactionManager transactionManager,
@Qualifier("dataSource") DataSource dataSource) throws Exception {
JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
jobRepositoryFactoryBean.setDataSource(dataSource);
jobRepositoryFactoryBean.setTransactionManager(transactionManager);
jobRepositoryFactoryBean.setDatabaseType("POSTGRES");
return jobRepositoryFactoryBean.getObject();
}
При необходимости я могу предоставить любую другую информацию. Другой вопрос — если бы я использовал один и тот же код в основном, менеджер транзакций, менеджер сущностей и т. Д. Как старый мой код работал на 1.x.x? Могла ли у меня быть неправильная зависимость где-то в моем pom.xml таким образом, мой новый перенесенный код использует неправильный метод или что-то из неправильной зависимости?
Ответ №1:
По умолчанию @EnableBatchProcessing
настраивает пакет Spring для использования a DataSourceTransactionManager
, если вы предоставляете a DataSource
. Этот менеджер транзакций ничего не знает о вашем контексте JPA. Поэтому, если вы хотите использовать репозиторий JPA для сохранения данных, вам необходимо настроить пакет Spring для использования JpaTransactionManager
.
Теперь, чтобы предоставить пользовательский менеджер транзакций, вам нужно зарегистрировать BatchConfigurer
и переопределить getTransactionManager()
метод, что-то вроде:
@Bean
public BatchConfigurer batchConfigurer(DataSource dataSource) {
return new DefaultBatchConfigurer(dataSource) {
@Override
public PlatformTransactionManager getTransactionManager() {
return new JpaTransactionManager();
}
};
}
Это объясняется в разделе Настройка задания и в разделе Javadoc @EnableBatchProcessing
.