当 运行 单个作业、SERIALIZED 隔离级别时无法序列化此事务的访问

Can't serialize access for this transaction when running single job, SERIALIZED isolation level

如何为整个批次设置一个隔离级别?

实际上我设置的 isolationLevel 如下:

* 更新配置 class*

@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 批处理想要使用其技术表时,隔离级别从 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

这会触发无法序列化异常。

根据您当前的配置,您在 Spring 应用程序上下文中声明的 JobRepository 类型的 bean 将不会被 Spring Batch 拾取。它实际上是默认的(由 @EnableBatchProcessing 创建),默认使用 SERIALIZABLE 隔离级别。

如参考文档Configuring a JobRepository部分所述,您需要实现BatchConfigurer接口并在您的配置中提供该类型的bean,或者使您的配置class 扩展 DefaultBatchConfigurer 并覆盖 createJobRepository.