«DefaultJpaDialect не поддерживает пользовательские уровни изоляции» при обновлении до весеннего пакета 5.JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 «DefaultJpaDialect не поддерживает пользовательские уровни изоляции» при обновлении до весеннего пакета 5.

Сообщение Anonymous »

Я обновляю приложение до новейшей версии Spring Boot 3, и из-за этого Spring Batch обновляется до 5.2.3 (с 4.3.10).
Раньше приложение не сохраняло состояния пакета, оно использовало репозиторий заданий «на основе карты».
Поскольку этот репозиторий на основе карты полностью удален в версии 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();
По сути, я добавил tx-менеджер платформы в качестве второго параметра в метод chunk(...).
Я также создал необходимые таблицы и последовательности для схемы базы данных (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)

Я попробовал и завершил свою фабрикуentityManagerFactory с настройкой hibernate.connection.release_mode", "on_close"

Код: Выделить всё

    @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();
}
и завершил hibernateJpaDialect с настройками «setPrepareConnection(true)»

Код: Выделить всё

    @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;
}
Но все равно получил то же самое исключение «HibernateJpaDialect не разрешено поддерживать пользовательские уровни изоляции...»
.

Вторая попытка: настроить пакетную службу через @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);
}
}
С этим экземпляром DataSourceTransactionManager задания Spring-Batch
начали работать.
Поэтому кажется, что у меня есть рабочее решение.
Было бы обнадеживающе получить отзыв, действительно ли это правильное
решение или нет?
Кроме того, я немного обеспокоен тем, что использую два разных TransactionManager
(a JpaTransactionManager для приложения и DataSourceTransactionManager
для Spring-Batch) с ОДНИМ источником данных.
Безопасно ли это? Или мне следует настроить отдельный источник данных для
DataSourceTransactionManager?

Подробнее здесь: https://stackoverflow.com/questions/798 ... ading-to-s
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»