java - 内部事务(REQUIRES_NEW)抛出异常时外部事务回滚

标签 java spring spring-data-jpa spring-transactions

我有方法:

  @Transactional
  public void importChargesRequest() {
  ...
   for (Charge charge : charges) {

      try {
        Charge savedCharge = saveCharge(charge);
      } catch (Exception e) {
        log.error(e.getMessage());
      }
    }
}

为了坚持每个 Charge 我调用内部方法:

@Transactional(propagation = Propagation.REQUIRES_NEW)
  public Charge saveCharge(Charge charge) {
    return chargesRepository.saveAndFlush(charge);
  }

如果 saveCharge 方法抛出异常(在我的例子中是约束异常)我想写日志,并继续保留另一个实体。但是当我捕获异常时——我的外部事务回滚有错误:

Transaction was marked for rollback only; cannot commit; nested exception is org.hibernate.TransactionException: Transaction was marked for rollback only; cannot commit

我需要打开事务并开始保存每个实体。如果某些实体无法保存异常 - 我需要记录此异常并继续保存其他实体。当所有实体都将保存(或记录)时,我需要提交外部事务。但是现在它回滚了。我该如何解决?

编辑:

我接受了评论并将 REQUIRES_NEW 事务移动到另一个 bean:

@Service
public class TestService {

  private final TestDao testDao;

  public TestService(TestDao testDao) {
    this.testDao = testDao;
  }

  @Transactional
  public void saveTest() {
    for (int i = 0; i < 100; i++) {
      Test test = new Test();
      if (i == 10 || i == 20) {
        test.setName("123");
      } else {
        test.setName(UUID.randomUUID().toString());
      }
      testDao.save(test);
    }
  }
} 

和每个内部事务的另一个 bean:

@Slf4j
@Component
@Repository
public class TestDao {

  @PersistenceContext
  private EntityManager entityManager;

  @Transactional(propagation = Propagation.REQUIRES_NEW)
  public void save(Test test) {
    entityManager.persist(test);
  }
}

当我第一次尝试保存时,数据库中有 20 行。每次下一次保存我都会得到 +10 行。名字有约束。当我收到错误时 - 事务已提交且未继续。每次保存后我等待 98 行。

最佳答案

您应该将方法 saveCharge 移至其他类 因为 spring 事务使用代理模式,这需要其他类。

新建服务类并注入(inject)主类

例如:

@Service
public class A{

@Autowire
private B b;

@Transactional
  public void importChargesRequest() {
  ...
   for (Charge charge : charges) {

      try {
        Charge savedCharge = b.saveCharge(charge);
      } catch (Exception e) {
        log.error(e.getMessage());
      }
    }
}
}

@Service
public class B{

@Transactional(propagation = Propagation.REQUIRES_NEW)
  public Charge saveCharge(Charge charge) {
    return chargesRepository.saveAndFlush(charge);
  }
}

关于java - 内部事务(REQUIRES_NEW)抛出异常时外部事务回滚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51841562/

相关文章:

java - 在 JTable 上使用游标调整单个行高

java - 使用 HashMap 时,值和键在迭代时是否保证顺序相同?

java - MongoCollection 与 DBCollection java

java - BeforeAll 方法中没有为参数注册 ParameterResolver

spring - 我们可以更改 DispatcherServlet 上下文配置文件名吗?

java - 我们想将字段值与结果值结合起来以产生结果作为映射图

带有分页的 Spring Data 和 Native Query

java - Spring : can't persist entity annotated with @JsonIgnore

java - 启用 SSL 的 Spring Boot 阻塞连接池

java - spring-data-jpa 1.9.4 升级到 1.10.2 后出现问题