Не удается сериализовать доступ к этой транзакции при выполнении одного задания, СЕРИАЛИЗОВАННЫЙ уровень изоляции

#spring-boot #transactions #spring-batch #isolation-level

#весенняя загрузка #транзакции #spring-batch #уровень изоляции

Вопрос:

Как установить один уровень изоляции для всего пакета?

На самом деле я устанавливаю IsolationLevel, как показано ниже :

* Обновить класс конфигурации*

 @Configuration

@EnableBatchProcessing

public class ApplicationBatchConfig {



                private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationBatchConfig.class);



                @Autowired

                private Environment environment;



                /**

                * Bean - Datasource <Br>
                *
                * @return DataSource
                */
                @Bean(name = "dataSource")

                @ConfigurationProperties(prefix = "spring.datasource")

                public DataSource dataSource() {
                  return DataSourceBuilder.create().build();
                }


                /**

                * @param dataSource 

                * @param transactionManager 

                * @return JobRepository

                * @throws Exception

                */

                @Bean(name = "jobRepository")

                public JobRepository jobRepository(final DataSource dataSource, final PlatformTransactionManager transactionManager) throws Exception {

                               final JobRepositoryFactoryBean rc = new JobRepositoryFactoryBean();

                               rc.setDatabaseType("ORACLE");

                               rc.setDataSource(dataSource);

                               rc.setTransactionManager(transactionManager);

                               rc.setIsolationLevelForCreate("ISOLATION_READ_COMMITTED");
                               return rc.getObject();

                }

                /**

                *

                 * @return PropertySourcesPlaceholderConfigurer

                */

                @Bean

                public static PropertySourcesPlaceholderConfigurer propertyConfigurer() {

                               String location = System.getProperty("ext.properties.dir");

                               if (!StringUtils.hasText(location)) {

                                               LOGGER.warn("utilisation repertoire properties par defaut");

                                               location = "classpath:";

                               }

                               final PropertySourcesPlaceholderConfigurer ppc = new PropertySourcesPlaceholderConfigurer();

                               String propertiesLocation;

                               String propertiesBatchLocation;

                               String propertiesLogLocation;

                               String propertiesAppliLocation;



                               if (location.startsWith("classpath:")) {

                                               propertiesLocation = location.replaceFirst("classpath:", "");

                                               if (StringUtils.hasText(propertiesLocation)) {

                                                               propertiesBatchLocation = propertiesLocation   "/"   IConstantBatch.BATCH_PROPERTIES;

                                                               propertiesLogLocation = propertiesLocation   "/"   IConstantBatch.LOG4J_PROPERTIES;

                                                               propertiesAppliLocation = propertiesLocation   "/"   IConstantBatch.APPLI_PROPERTIES;

                                               } else {

                                                               propertiesBatchLocation = IConstantBatch.BATCH_PROPERTIES;

                                                               propertiesLogLocation = IConstantBatch.LOG4J_PROPERTIES;

                                                               propertiesAppliLocation = IConstantBatch.APPLI_PROPERTIES;

                                               }

                                               ppc.setLocations(new Resource[] { new ClassPathResource(propertiesBatchLocation), new ClassPathResource(propertiesLogLocation),

                                                                              new ClassPathResource(propertiesAppliLocation) });

                               } else {

                                               propertiesLocation = location;

                                               propertiesBatchLocation = propertiesLocation   "/"   IConstantBatch.BATCH_PROPERTIES;

                                               propertiesLogLocation = propertiesLocation   "/"   IConstantBatch.LOG4J_PROPERTIES;

                                               propertiesAppliLocation = propertiesLocation   "/"   IConstantBatch.APPLI_PROPERTIES;

                                               // ajout des fichier de properties

                                               ppc.setLocations(new Resource[] { new FileSystemResource(propertiesBatchLocation), new FileSystemResource(propertiesLogLocation),

                                                                              new FileSystemResource(propertiesAppliLocation) });



                               }

                               ppc.setIgnoreResourceNotFound(true);

                               ppc.setFileEncoding(IConstantBatch.PROPERTIES_ENCODING);

                               ppc.setOrder(1);

                               ppc.setIgnoreUnresolvablePlaceholders(true);

                               LOGGER.info(" repertoire de configuration batch utilisé : {}", propertiesLocation);



                               return ppc;



                }
}
  

Но во время выполнения, когда spring batch хочет использовать свои технические таблицы, уровень изоляции переключается с 2 на 8 — смотрите журнал ниже

* Журнал обновлений*

       ================================================================================

    2019-03-25 14:52:43.129 DEBUG 11624 --- [           main] o.s.j.d.DataSourceTransactionManager     : Creating new transaction with name [org.springframework.batch.core.repository.support.SimpleJobRepository.getLastJobExecution]: PROPAGATION_REQUIRES_NEW,ISOLATION_SERIALIZABLE

    2019-03-25 14:52:43.129 DEBUG 11624 --- [           main] o.s.j.d.DataSourceTransactionManager     : Acquired Connection [ProxyConnection[PooledConnection[oracle.jdbc.driver.T4CConnection@eb397d18]]] for JDBC transaction

    2019-03-25 14:52:43.129 DEBUG 11624 --- [           main] o.s.jdbc.datasource.DataSourceUtils      : Changing isolation level of JDBC Connection [ProxyConnection[PooledConnection[oracle.jdbc.driver.T4CConnection@eb397d18]]] to 8

    2019-03-25 14:52:43.129 DEBUG 11624 --- [           main] o.s.j.d.DataSourceTransactionManager     : Switching JDBC Connection [ProxyConnection[PooledConnection[oracle.jdbc.driver.T4CConnection@eb397d18]]] to manual commit

    2019-03-25 14:52:43.129 TRACE 11624 --- [           main] .s.t.s.TransactionSynchronizationManager : Bound value [org.springframework.jdbc.datasource.ConnectionHolder@452fee11] for key [org.apache.tomcat.jdbc.pool.DataSource@375faa9d{ConnectionPool[defaultAutoCommit=null; defaultReadOnly=null; defaultTransactionIsolation=-1; defaultCatalog=null; driverClassName=oracle.jdbc.driver.OracleDriver; maxActive=100; maxIdle=100; minIdle=10; initialSize=10; maxWait=30000; testOnBorrow=false; testOnReturn=false; timeBetweenEvictionRunsMillis=5000; numTestsPerEvictionRun=0; minEvictableIdleTimeMillis=60000; testWhileIdle=false; testOnConnect=false; password=********; url=jdbc:oracle:thin:@********; username=********; validationQuery=null; validationQueryTimeout=-1; validatorClassName=null; validationInterval=3000; accessToUnderlyingConnectionAllowed=true; removeAbandoned=false; removeAbandonedTimeout=60; logAbandoned=false; connectionProperties=null; initSQL=null; jdbcInterceptors=null; jmxEnabled=true; fairQueue=true; useEquals=true; abandonWhenPercentageFull=0; maxAge=0; useLock=false; dataSource=null; dataSourceJNDI=null; suspectTimeout=0; alternateUsernameAllowed=false; commitOnReturn=false; rollbackOnReturn=false; useDisposableConnectionFacade=true; logValidationErrors=false; propagateInterruptState=false; ignoreExceptionOnPreLoad=false; useStatementFacade=true; }] to thread [main]

    2019-03-25 14:52:43.129 TRACE 11624 --- [           main] .s.t.s.TransactionSynchronizationManager : Initializing transaction synchronization

    2019-03-25 14:52:43.129 TRACE 11624 --- [           main] o.s.t.i.TransactionInterceptor           : Getting transaction for [org.springframework.batch.core.repository.support.SimpleJobRepository.getLastJobExecution]

    2019-03-25 14:52:43.129 DEBUG 11624 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL query

    2019-03-25 14:52:43.129 DEBUG 11624 --- [           main] o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?]

    2019-03-25 14:52:43.129 TRACE 11624 --- [           main] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@452fee11] for key [org.apache.tomcat.jdbc.pool.DataSource@375faa9d{ConnectionPool[defaultAutoCommit=null; defaultReadOnly=null; defaultTransactionIsolation=-1; defaultCatalog=null; driverClassName=oracle.jdbc.driver.OracleDriver; maxActive=100; maxIdle=100; minIdle=10; initialSize=10; maxWait=30000; testOnBorrow=false; testOnReturn=false; timeBetweenEvictionRunsMillis=5000; numTestsPerEvictionRun=0; 

............

    o.s.jdbc.core.JdbcTemplate               : Executing prepared SQL statement [INSERT into BATCH_JOB_INSTANCE(JOB_INSTANCE_ID, JOB_NAME, JOB_KEY, VERSION) values (?, ?, ?, ?)]

    2019-03-25 14:52:43.191 TRACE 11624 --- [           main] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@d40e102f] for key [org.apache.tomcat.jdbc.pool.DataSource@375faa9d{ConnectionPool[defaultAutoCommit=null; defaultReadOnly=null; defaultTransactionIsolation=-1; defaultCatalog=null; driverClassName=oracle.jdbc.driver.OracleDriver; maxActive=100; maxIdle=100; minIdle=10; initialSize=10; maxWait=30000; testOnBorrow=false; testOnReturn=false; timeBetweenEvictionRunsMillis=5000; numTestsPerEvictionRun=0; minEvictableIdleTimeMillis=60000; testWhileIdle=false; testOnConnect=false; password=********; url=jdbc:oracle:thin:@*********; username=*******; validationQuery=null; validationQueryTimeout=-1; validatorClassName=null; validationInterval=3000; accessToUnderlyingConnectionAllowed=true; removeAbandoned=false; removeAbandonedTimeout=60; logAbandoned=false; connectionProperties=null; initSQL=null; jdbcInterceptors=null; jmxEnabled=true; fairQueue=true; useEquals=true; abandonWhenPercentageFull=0; maxAge=0; useLock=false; dataSource=null; dataSourceJNDI=null; suspectTimeout=0; alternateUsernameAllowed=false; commitOnReturn=false; rollbackOnReturn=false; useDisposableConnectionFacade=true; logValidationErrors=false; propagateInterruptState=false; ignoreExceptionOnPreLoad=false; useStatementFacade=true; }] bound to thread [main]

    2019-03-25 14:52:43.191 TRACE 11624 --- [           main] .s.t.s.TransactionSynchronizationManager : Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@d40e102f] for key [org.apache.tomcat.jdbc.pool.DataSource@375faa9d{ConnectionPool[defaultAutoCommit=null; defaultReadOnly=null; defaultTransactionIsolation=-1; defaultCatalog=null; driverClassName=oracle.jdbc.driver.OracleDriver; maxActive=100; maxIdle=100; minIdle=10; initialSize=10; maxWait=30000; testOnBorrow=false; testOnReturn=false; timeBetweenEvictionRunsMillis=5000; numTestsPerEvictionRun=0; minEvictableIdleTimeMillis=60000; testWhileIdle=false; testOnConnect=false; password=********; url=jdbc:oracle:thin:@*********; username=*******; validationQuery=null; validationQueryTimeout=-1; validatorClassName=null; validationInterval=3000; accessToUnderlyingConnectionAllowed=true; removeAbandoned=false; removeAbandonedTimeout=60; logAbandoned=false; connectionProperties=null; initSQL=null; jdbcInterceptors=null; jmxEnabled=true; fairQueue=true; useEquals=true; abandonWhenPercentageFull=0; maxAge=0; useLock=false; dataSource=null; dataSourceJNDI=null; suspectTimeout=0; alternateUsernameAllowed=false; commitOnReturn=false; rollbackOnReturn=false; useDisposableConnectionFacade=true; logValidationErrors=false; propagateInterruptState=false; ignoreExceptionOnPreLoad=false; useStatementFacade=true; }] bound to thread [main]

    2019-03-25 14:52:43.191 TRACE 11624 --- [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 1, parameter value [701], value class [java.lang.Long], SQL type -5

    2019-03-25 14:52:43.191 TRACE 11624 --- [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 2, parameter value [HierarchyEntrepriseService], value class [java.lang.String], SQL type 12

    2019-03-25 14:52:43.191 TRACE 11624 --- [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 3, parameter value [cee0f40db33d9d28023aebe0d48e0839], value class [java.lang.String], SQL type 12

    2019-03-25 14:52:43.191 TRACE 11624 --- [           main] o.s.jdbc.core.StatementCreatorUtils      : Setting SQL statement parameter value: column index 4, parameter value [0], value class [java.lang.Integer], SQL type 4
  

И это вызывает исключение «Не удается сериализовать».

Комментарии:

1. Похоже, что ваш репозиторий заданий не учитывается в вашей конфигурации. Пожалуйста, опубликуйте конфигурацию вашего пакета, а также полную трассировку стека.

2. @MahmoudBenHassine Все сделано, я обновил свой вопрос

3. Спасибо. Я добавил ответ.

Ответ №1:

При вашей текущей конфигурации компонент типа JobRepository , который вы объявили в контексте приложения Spring, не будет тем, который будет получен Spring Batch. На самом деле будет использоваться стандартный (созданный @EnableBatchProcessing ), который по умолчанию использует SERIALIZABLE уровень изоляции.

Как упоминалось в разделе «Настройка JobRepository» справочной документации, вам необходимо реализовать BatchConfigurer интерфейс и предоставить компонент этого типа в вашей конфигурации, или расширить ваш класс конфигурации DefaultBatchConfigurer и переопределить createJobRepository .