How to set one isolation level for the whole batch ?
Actually I'm setting isolationLevel like below :
* Update Config 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;
}
}
But during the running when spring batch want to use its technicals tables the isolation level is switched from 2 to 8 - see the log below
* Update Log*
================================================================================
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
And that trigger a Can't Serialize exception.
With your current configuration, the bean of type JobRepository
that you declared in your Spring application context will not be the one picked up by Spring Batch. It is actually the default one (created by @EnableBatchProcessing
) that will be used, which uses the SERIALIZABLE
isolation level by default.
As mentioned in the Configuring a JobRepository section of the reference documentation, you need to implement the BatchConfigurer
interface and provide a bean of that type in your configuration, or make your configuration class extend DefaultBatchConfigurer
and override createJobRepository
.