Раньше приложение не сохраняло состояния пакета, оно использовало репозиторий заданий «на основе карты».
Поскольку этот репозиторий на основе карты полностью удален в версии 5, мне приходится перейти на репозиторий на основе таблиц JDBC. Я прочитал руководство по миграции ( https://github.com/spring-projects/spri ... tion-Guide ) и в соответствии с ним изменил следующую часть приложения:
Код: Выделить всё
return new StepBuilder("cnyProcessStep", jobRepository) //
.allowStartIfComplete(true)//
. chunk(1)
.reader(cnyPushItemReader) //
.processor(compositeProcessor) //
.writer(cnyPushItemWriter) //
.faultTolerant()
.skipPolicy((t, skipCount) -> true) //
.listener(defaultBatchListener) //
.transactionAttribute(new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_NEVER))
.build();
Код: Выделить всё
...
@Autowired
private PlatformTransactionManager transactionManager;
...
return new StepBuilder("cnyProcessStep", jobRepository) //
.allowStartIfComplete(true)//
. chunk(1, transactionManager)
.reader(cnyPushItemReader) //
.processor(compositeProcessor) //
.writer(cnyPushItemWriter) //
.faultTolerant()
.skipPolicy((t, skipCount) -> true) //
.listener(defaultBatchListener) //
.transactionAttribute(new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_NEVER))
.build();
Я также создал необходимые таблицы и последовательности для схемы базы данных (schema-oracle.sql из артефакта пакетного ядра).
После этих изменений задание выдает следующее исключение при выполнении:
Код: Выделить всё
...
Caused by: org.springframework.transaction.InvalidIsolationLevelException: DefaultJpaDialect does not support custom isolation levels due to limitations in standard JPA. Specific arrangements may be implemented in custom JpaDialect variants.
at org.springframework.orm.jpa.DefaultJpaDialect.beginTransaction(DefaultJpaDialect.java:64)
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:421)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.startTransaction(AbstractPlatformTransactionManager.java:532)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:405)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:639)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:374)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
at jdk.proxy2/jdk.proxy2.$Proxy375.getLastJobExecution(Unknown Source)
at org.springframework.batch.core.launch.support.TaskExecutorJobLauncher.run(TaskExecutorJobLauncher.java:109)
Первая идея: настроить HibernateJpaDialect
Это проект JPA, и менеджер tx в Spring был настроен как экземпляр JpaTransactionManager.
Этот JpaTransactionManager по умолчанию использует экземпляр DefaultJpaDialect и ".beginTransaction"
метод там выдает исключение «DefaultJpaDialect не поддерживает пользовательские уровни изоляции...».
Поскольку мы используем Hibernate в качестве реализации JPA в проекте, моей первой мыслью было указать
HibernateJpaDialect (вместо значения по умолчанию) в нашей конфигурации базы данных следующим образом:
Код: Выделить всё
@Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory());
transactionManager.setDataSource(dataSource);
transactionManager.setJpaDialect(new HibernateJpaDialect());
return transactionManager;
}
Код: Выделить всё
Caused by: org.springframework.transaction.InvalidIsolationLevelException: HibernateJpaDialect is not allowed to support custom isolation levels: make sure that its 'prepareConnection' flag is on (the default) and that the Hibernate connection release mode is set to ON_CLOSE.
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:168)
at org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:421)
Код: Выделить всё
@Bean
public EntityManagerFactory entityManagerFactory() {
LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
factoryBean.setDataSource(dataSource);
factoryBean.setPackagesToScan(
...
);
factoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
Properties properties = new Properties();
...
properties.put("hibernate.connection.release_mode", "on_close");
factoryBean.setJpaProperties(properties);
factoryBean.afterPropertiesSet();
return factoryBean.getObject();
}
Код: Выделить всё
@Bean
public PlatformTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory());
transactionManager.setDataSource(dataSource);
transactionManager.setDefaultTimeout(txTimeoutInSeconds);
HibernateJpaDialect hibernateJpaDialect = new HibernateJpaDialect();
hibernateJpaDialect.setPrepareConnection(true);
transactionManager.setJpaDialect(hibernateJpaDialect);
return transactionManager;
}
.
Вторая попытка: настроить пакетную службу через @EnableBatchProcessing(transactionManagerRef = "...")
После этого я попытался настроить отдельный tx-менеджер для Spring Batch через
@EnableBatchProcessing(transactionManagerRef = "someOtherTxManRef") аннотация:
Код: Выделить всё
@Configuration
@EnableBatchProcessing(transactionManagerRef = "batchTransactionManager")
public class BatchConfig {
@Bean(defaultCandidate = false, name = "batchTransactionManager")
public DataSourceTransactionManager batchTransactionManager(DataSource ds) {
return new DataSourceTransactionManager(ds);
}
}
начали работать.
Поэтому кажется, что у меня есть рабочее решение.
Было бы обнадеживающе получить отзыв, действительно ли это правильное
решение или нет?
Кроме того, я немного обеспокоен тем, что использую два разных TransactionManager
(a JpaTransactionManager для приложения и DataSourceTransactionManager
для Spring-Batch) с ОДНИМ источником данных.
Безопасно ли это? Или мне следует настроить отдельный источник данных для
DataSourceTransactionManager?
Подробнее здесь: https://stackoverflow.com/questions/798 ... ading-to-s
Мобильная версия