【问题标题】:How to disable transaction management in Spring Batch如何在 Spring Batch 中禁用事务管理
【发布时间】: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


【解决方案1】:

您必须启用它们而不是禁用事务,因为没有事务您将无法使用数据库。您可以像在通常的应用程序中一样创建它们(连接到数据库、打开事务、关闭事务、关闭连接),但是使用 spring 您可以使用 @Transactional 注释或使用 xml 配置来执行此操作。

【讨论】:

    猜你喜欢
    • 2014-12-01
    • 2018-02-24
    • 2013-07-30
    • 2015-05-31
    • 2021-02-07
    • 1970-01-01
    • 2021-02-20
    • 2019-01-25
    • 1970-01-01
    相关资源
    最近更新 更多