#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
.