当前位置: 首页 > 知识库问答 >
问题:

Spring Batch CompositeItemWriter事务回滚问题

姜兴业
2023-03-14

总之,我在使用Spring Batch CompositeItemWriter时遇到了事务回滚问题。Spring batch的版本为2.2.7。

我的配置与此处的帖子相同:https://stackoverflow.com/questions/32432519/compositeitemwriter-doesnt-roll-back-in-spring-batch

<bean id="compositeItemWriter" class="org.springframework.batch.item.support.CompositeItemWriter">
    <property name="delegates">
    <list>
        <ref bean="firstItemWriter"/>
        <ref bean="secondItemWriter"/>
        <ref bean="thirdItemWriter"/>
    </list>
    </property>
</bean>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
    <property name="dataSource" ref="dataSource"/>
</bean> 

<bean id="dataSource"
    class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${batch.jdbc.driver}" />
    <property name="url" value="${batch.jdbc.url}" />
    <property name="username" value="${batch.jdbc.user}" />
    <property name="password" value="${batch.jdbc.password}" />
</bean>

当第三个ItemWriter抛出异常时,以前写入数据库的数据不会回滚。

不确定我遗漏了什么,但我的理解是,复合项编写器共享相同的事务,所有数据都应该在发生异常时回滚。

欢迎任何建议

共有2个答案

叶淇
2023-03-14

制作自定义compositeItemWrite。”@“事务”适用于我的代码。

package com.krafton.intraplatform.batch.job.step;

import java.util.Iterator;
import java.util.List;

import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.ItemStreamWriter;
import org.springframework.batch.item.ItemWriter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

public class CustomCompositeWriter<T> implements ItemStreamWriter<T>, InitializingBean {
  private List<ItemWriter<? super T>> delegates;
  private boolean ignoreItemStream = false;

  public CustomCompositeWriter() {
  }

  public void setIgnoreItemStream(boolean ignoreItemStream) {
    this.ignoreItemStream = ignoreItemStream;
  }


  @Transactional
  public void write(List<? extends T> item) throws Exception {
    Iterator var2 = this.delegates.iterator();

    while(var2.hasNext()) {
      ItemWriter<? super T> writer = (ItemWriter)var2.next();
      writer.write(item);
    }

  }

  public void afterPropertiesSet() throws Exception {
    Assert.notNull(this.delegates, "The 'delegates' may not be null");
    Assert.notEmpty(this.delegates, "The 'delegates' may not be empty");
  }

  public void setDelegates(List<ItemWriter<? super T>> delegates) {
    this.delegates = delegates;
  }

  public void close() throws ItemStreamException {
    Iterator var1 = this.delegates.iterator();

    while(var1.hasNext()) {
      ItemWriter<? super T> writer = (ItemWriter)var1.next();
      if (!this.ignoreItemStream && writer instanceof ItemStream) {
        ((ItemStream)writer).close();
      }
    }

  }

  public void open(ExecutionContext executionContext) throws ItemStreamException {
    Iterator var2 = this.delegates.iterator();

    while(var2.hasNext()) {
      ItemWriter<? super T> writer = (ItemWriter)var2.next();
      if (!this.ignoreItemStream && writer instanceof ItemStream) {
        ((ItemStream)writer).open(executionContext);
      }
    }

  }

  public void update(ExecutionContext executionContext) throws ItemStreamException {
    Iterator var2 = this.delegates.iterator();

    while(var2.hasNext()) {
      ItemWriter<? super T> writer = (ItemWriter)var2.next();
      if (!this.ignoreItemStream && writer instanceof ItemStream) {
        ((ItemStream)writer).update(executionContext);
      }
    }

  }
}
养研
2023-03-14

经过几天的努力,终于找到了解决方案。关键是将所有写入程序放在一个事务中,并关闭自动提交。

public class TransactionAwareCompositeItemWritter<T> extends CompositeItemWriter<T> {
private static Logger LOG = LoggerFactory.getLogger(TransactionAwareCompositeItemWritter.class);

private List<ItemWriter<? super T>> delegates;

private PlatformTransactionManager transactionManager;

private JdbcTemplate jdbcTemplate;

@Override
public void write(final List<? extends T> item) throws Exception {

    Connection con = DataSourceUtils.getConnection(jdbcTemplate.getDataSource());

    if (con.getAutoCommit()) {

        LOG.debug("Switching JDBC Connection [" + con + "] to manual commit");

        con.setAutoCommit(false);
    }

    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
    def.setName("CompositeItemWriter Transaction");
    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

    TransactionStatus status = transactionManager.getTransaction(def);
    try {
        for (ItemWriter<? super T> writer : delegates) {
            writer.write(item);
        }
    } catch (Exception e) {
        transactionManager.rollback(status);
        throw e;
    }

    transactionManager.commit(status);

    if (!con.getAutoCommit()) {

        LOG.debug("Switching JDBC Connection [" + con + "] to auto commit");

        con.setAutoCommit(true);
    }

}

public void setDelegates(List<ItemWriter<? super T>> delegates) {
    super.setDelegates(delegates);
    this.delegates = delegates;
}

public PlatformTransactionManager getTransactionManager() {
    return transactionManager;
}

public void setTransactionManager(PlatformTransactionManager transactionManager) {
    this.transactionManager = transactionManager;
}

public JdbcTemplate getJdbcTemplate() {
    return jdbcTemplate;
}

public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
    this.jdbcTemplate = jdbcTemplate;
}

}

 类似资料:
  • 问题内容: 我在EJB3无状态会话Bean中使用CMT。另外,我还创建了自己的具有注释“ @ApplicationException(rollback = true)”的异常。 要回滚事务时是否必须使用“ context.setRollbackOnly()”? 我可以通过在bean的public方法内抛出异常来回滚事务吗? 如果是这样(对Q#2的回答是“是”),我是否必须通过在方法中声明异常来将异

  • 本文向大家介绍java事务回滚失败问题分析,包括了java事务回滚失败问题分析的使用技巧和注意事项,需要的朋友参考一下 Spring-Java事物回滚失效处理最近在做项目中,无意间发现有个类在抛事物回滚操作,数据也正常的插入到数据库当中了,于是仔细查看看一下具体原因。 一切还是要从Java的检查型异常和非检查型异常说起。 那么什么是检查型异常什么又是非检查型异常呢? 最简单的判断点有两个: 1.继

  • 我正在使用spring-test运行JUnit测试,我的代码如下所示 我的问题是我希望我的测试不影响其他测试。所以我想为每个测试创建一些类似回滚的东西。我为此找了很多,但到目前为止一无所获。我使用Hibernate和MySql来实现这个

  • -ZJ 以下是我在Application.Properties中的数据源设置:

  • 我在Spring Boot应用程序中有一个Javers实现。Mongo4.4被用作数据库。从MongoDB4.4开始,您可以在事务中创建文档。 我在创建对象时模拟了一个异常。如预期的那样,对象没有在数据库中创建,但是一个新的快照被添加到jv_snapshots集合中。 控制器:

  • 情景故事时间: 我“继承”了一个程序,一个用于访问数据库的相当简单的webservice。该程序在某个地方有一个缺陷:它试图更新一个没有更新授权的表。该程序只具有更新数据库队列的权限(Oracle),以保存谁访问了什么信息。这是不受欢迎的行为,现在我纠正了它。注意:这与这个问题本身无关,它只是导致我提出这个问题的原因。 该程序使用Spring+Hibernate来管理和访问数据和事务。 因为程序的