使用 Spring 批处理而不进行交易
Using Spring Batch Without Transaction
我有一个 Spring 批处理作业,它在第一步/tasklet 中调用另一个作业。当然,这不适用于作业默认处理事务的方式。
在我的应用程序中,我并不是真的那么需要事务,而且这些步骤也没有数据库连接,所以我宁愿完全删除事务。为此,对于这两项工作的每一步,我都执行了以下操作:
public Step stepX() {
return this.stepBuilderFactory
.get("stepX")
.tasklet(new StepXTasklet())
.transactionAttribute(transactionAttribute())
.build();
}
private TransactionAttribute transactionAttribute() {
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
attribute.setPropagationBehavior(Propagation.SUPPORTS.value());
return attribute;
}
应用程序仍然会抛出此异常:
org.springframework.dao.OptimisticLockingFailureException: Attempt to update step execution id=1 with wrong version (2), where current version is 3
at org.springframework.batch.core.repository.dao.MapStepExecutionDao.updateStepExecution(MapStepExecutionDao.java:106)
at org.springframework.batch.core.repository.support.SimpleJobRepository.update(SimpleJobRepository.java:196)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:353)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy150.update(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
出于某种原因,Spring Batch 如何显示其内部 TransactionSuspensionNotSupportedException
。
所以有些东西仍在使用交易,我只是不确定是什么以及如何删除它们。也许 JobExecutionListener
?也许是大块?
我倾向于块,因为在第二个块之后(按读取的行数计算)和第三个块之前我得到了输出:
Commit failed while step execution data was already updated. Reverting to old version.
以防万一,父作业是“流程”作业,子作业是“reader-transformer-writer”。
Spring 批处理作业框架的哪些部分使用事务,我如何确保这些部分停止使用它们?
问题出在默认作业存储库上。似乎它的事务处理 is buggy。要解决此问题,请将其替换为具有内存数据库的 JDBC 作业存储库。只需将此 class 添加到 Spring 上下文:
@Configuration
@EnableBatchProcessing
public class InMemoryBatchContextConfigurer extends DefaultBatchConfigurer {
@Override
protected JobRepository createJobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDatabaseType(DatabaseType.H2.getProductName());
factory.setDataSource(dataSource());
factory.setTransactionManager(getTransactionManager());
return factory.getObject();
}
public DataSource dataSource() {
EmbeddedDatabaseBuilder embeddedDatabaseBuilder = new EmbeddedDatabaseBuilder();
return embeddedDatabaseBuilder
.addScript("classpath:org/springframework/batch/core/schema-drop-h2.sql")
.addScript("classpath:org/springframework/batch/core/schema-h2.sql")
.setType(EmbeddedDatabaseType.H2).build();
}
}
我有一个 Spring 批处理作业,它在第一步/tasklet 中调用另一个作业。当然,这不适用于作业默认处理事务的方式。
在我的应用程序中,我并不是真的那么需要事务,而且这些步骤也没有数据库连接,所以我宁愿完全删除事务。为此,对于这两项工作的每一步,我都执行了以下操作:
public Step stepX() {
return this.stepBuilderFactory
.get("stepX")
.tasklet(new StepXTasklet())
.transactionAttribute(transactionAttribute())
.build();
}
private TransactionAttribute transactionAttribute() {
DefaultTransactionAttribute attribute = new DefaultTransactionAttribute();
attribute.setPropagationBehavior(Propagation.SUPPORTS.value());
return attribute;
}
应用程序仍然会抛出此异常:
org.springframework.dao.OptimisticLockingFailureException: Attempt to update step execution id=1 with wrong version (2), where current version is 3
at org.springframework.batch.core.repository.dao.MapStepExecutionDao.updateStepExecution(MapStepExecutionDao.java:106)
at org.springframework.batch.core.repository.support.SimpleJobRepository.update(SimpleJobRepository.java:196)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:353)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy150.update(Unknown Source)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
出于某种原因,Spring Batch 如何显示其内部 TransactionSuspensionNotSupportedException
。
所以有些东西仍在使用交易,我只是不确定是什么以及如何删除它们。也许 JobExecutionListener
?也许是大块?
我倾向于块,因为在第二个块之后(按读取的行数计算)和第三个块之前我得到了输出:
Commit failed while step execution data was already updated. Reverting to old version.
以防万一,父作业是“流程”作业,子作业是“reader-transformer-writer”。
Spring 批处理作业框架的哪些部分使用事务,我如何确保这些部分停止使用它们?
问题出在默认作业存储库上。似乎它的事务处理 is buggy。要解决此问题,请将其替换为具有内存数据库的 JDBC 作业存储库。只需将此 class 添加到 Spring 上下文:
@Configuration
@EnableBatchProcessing
public class InMemoryBatchContextConfigurer extends DefaultBatchConfigurer {
@Override
protected JobRepository createJobRepository() throws Exception {
JobRepositoryFactoryBean factory = new JobRepositoryFactoryBean();
factory.setDatabaseType(DatabaseType.H2.getProductName());
factory.setDataSource(dataSource());
factory.setTransactionManager(getTransactionManager());
return factory.getObject();
}
public DataSource dataSource() {
EmbeddedDatabaseBuilder embeddedDatabaseBuilder = new EmbeddedDatabaseBuilder();
return embeddedDatabaseBuilder
.addScript("classpath:org/springframework/batch/core/schema-drop-h2.sql")
.addScript("classpath:org/springframework/batch/core/schema-h2.sql")
.setType(EmbeddedDatabaseType.H2).build();
}
}