【发布时间】:2017-08-04 07:47:19
【问题描述】:
我们正在使用 Spring Batch 来运行我们的数据处理步骤。在每一步中,我们都有不使用事务管理的代码。我们得到“java.sql.SQLException:连接已经关闭。”在春季批处理中运行时,我们的数据库操作会出现异常,因为它会启动事务中的每个步骤。有人可以建议一种方法来禁用它们。
[编辑] 我正在寻找一个类似这里提到的选项http://forum.spring.io/forum/spring-projects/batch/91158-legacy-integration-tasklet-transaction。此解决方案不适用于我的情况。
[编辑] 我找到了一种方法来清除 jdbc 模板中的事务,运行我的代码并将它们初始化回来。它对我有用。这是一个合适的方法吗?
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import java.util.List;
public class MyTasklet implements Tasklet {
@Override
public RepeatStatus execute(StepContribution stepContribution, ChunkContext chunkContext) throws Exception {
TransactionStatus transactionStatus = getTransactionSynchronizationsAndClear();
try {
/**
* execute my code
*/
} finally {
initTransactionSyncs(transactionStatus);
}
return RepeatStatus.FINISHED;
}
private void initTransactionSyncs(TransactionStatus status) {
try {
TransactionSynchronizationManager.initSynchronization();
TransactionSynchronizationManager.setCurrentTransactionName(status.getName());
TransactionSynchronizationManager.setActualTransactionActive(status.isActive());
TransactionSynchronizationManager.setCurrentTransactionReadOnly(status.isReadOnly());
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(status.getIsolationLevel());
for (TransactionSynchronization sync : GainsightCollectionUtils.nullSafeList(status.getSyncs())) {
TransactionSynchronizationManager.registerSynchronization(sync);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private TransactionStatus getTransactionSynchronizationsAndClear() {
try {
TransactionStatus transactionStatus = new TransactionStatus();
transactionStatus.setSyncs(TransactionSynchronizationManager.getSynchronizations());
transactionStatus.setName(TransactionSynchronizationManager.getCurrentTransactionName());
transactionStatus.setReadOnly(TransactionSynchronizationManager.isCurrentTransactionReadOnly());
transactionStatus.setIsolationLevel(TransactionSynchronizationManager.getCurrentTransactionIsolationLevel());
transactionStatus.setActive(TransactionSynchronizationManager.isActualTransactionActive());
TransactionSynchronizationManager.clear();
return transactionStatus;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private class TransactionStatus {
private String name;
private boolean readOnly;
private boolean active;
private Integer isolationLevel;
private List<TransactionSynchronization> syncs;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isReadOnly() {
return readOnly;
}
public void setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
}
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
public Integer getIsolationLevel() {
return isolationLevel;
}
public void setIsolationLevel(Integer isolationLevel) {
this.isolationLevel = isolationLevel;
}
public List<TransactionSynchronization> getSyncs() {
return syncs;
}
public void setSyncs(List<TransactionSynchronization> syncs) {
this.syncs = syncs;
}
}
}
【问题讨论】:
-
这听起来像XY problem。您的问题很可能不是由于事务的管理方式引起的,而是因为您的代码中某处存在错误。尝试禁用事务管理很可能不是您需要的解决方案。但是,如果不了解您的代码的功能,就无法帮助您解决真正的问题。
-
嗨@Jesper,我的数据库连接池设置为removeAbandonedTimeout=600sec,这意味着如果我的代码获得连接并保持超过10分钟,池将关闭它。通常,我们的单个 db 操作不会持续超过 10 分钟。启用事务后,只有一个连接用于在事务块中运行我的所有数据库操作(即 spring 批处理步骤),这将花费 10 多分钟。这就是我想在春季批处理中禁用交易的原因
标签: java spring jdbc transactions spring-batch