【问题标题】:Saving does not work when exception is handled处理异常时保存不起作用
【发布时间】:2019-05-20 23:04:48
【问题描述】:

我面临着一个我什至找不到调试方法的情况。

我有以下spring-data 存储库:

IntegrationLogRepository

public interface IntegrationLogRepository extends PagingAndSortingRepository<IntegrationLog, Long> {

}

FooRepository

public interface FooRepository extends PagingAndSortingRepository<Foo, Long> {

}

在我的业务逻辑上,我有如下内容:

IntegrationLog log = new IntegrationLog();
log.setTimestamp(new Date());

try {
    Foo foo = new Foo();

    // Build the Foo object...

    fooRepository.save(foo);
    log.setStatus("OK");
} catch (Exception e) {
    log.setStatus("NOK");
} finally {
    integrationLogRepository.save(log);
}

当集成运行良好时,log 会以OK 状态保存。一切顺利。但是当我遇到异常时,出于某种原因integrationLogRepository.save(log) 不会什么都不做。我什么都没有:没有抛出异常,我看不到任何休眠查询正在我的 WebLogic 控制台上执行。日志没有持久化...

关于为什么会发生这种情况的任何想法?

以下是我的依赖项:

compile 'org.springframework.boot:spring-boot-starter-data-rest'
compile 'org.springframework.boot:spring-boot-starter-security'
compile "org.springframework.boot:spring-boot-starter-web-services"
runtime 'org.springframework.boot:spring-boot-devtools'
compile 'org.springframework.boot:spring-boot-starter-data-jpa'
compile "org.springframework.boot:spring-boot-starter-websocket"
compile 'javax.servlet:javax.servlet-api:3.1.0'
compile 'org.hibernate:hibernate-core:5.1.16.Final'
compile 'org.hibernate:hibernate-validator:5.2.3.Final'
compile 'org.hibernate:hibernate-entitymanager:5.1.0.Final'

在 Spring Boot 1.5.15.RELEASE、Java 1.7 和 WebLogic 12.1.3 上运行。

谢谢!

【问题讨论】:

  • 是否假设整个方法中有@Transactional?
  • 你的意思是我的业务逻辑的方法?没有@Transactional ...应该有吗?你能解释一下为什么吗?
  • 我只是尝试用 @Transactional 注释它并得到相同的结果:没有任何反应:/
  • 好吧,你可以添加@Transactional(noRollbackFor = {Exception.class}) 来消除回滚作为罪魁祸首
  • 好的!我“解决了”它。用@Transactional(propagation = Propagation.NOT_SUPPORTED) 注释该方法似乎可以使其工作。现在,如果有人可以向我解释为什么,如果这是正确的事情,我很乐意给予奖励积分 n_n'

标签: java hibernate spring-boot spring-data


【解决方案1】:

抛出的异常也是回滚集成日志保存。 如果你想保存日志,你必须在保存时给它一个单独的事务。

将日志存储库抽象为服务,并在保存日志的服务方法上添加创建新事务的事务。

@Service
public class IntegrationLogService {

    private final IntegrationLogRepository logRepository;

    @Autowired
    public IntegrationLogService(IntegrationLogRepository logRepository) {
        this.logRepository = logRepository;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void save(Log log) {
        this.logRepository.save(log);
    }
}

在您的业务中替换

finally {
    integrationLogRepository.save(log);
}

finally {
    integrationLogService.save(log);
}

编辑

为什么在业务层设置@Transactional(propagation = Propagation.NOT_SUPPORTED) 会起作用?

要了解它为什么起作用,我们需要先看看在 spring 使用 org.springframework.data.repository.CrudRepository 的存储库上调用 save 时会发生什么。

Spring 尝试确定方法和 targetClass 上的TransactionAttribute。对于方法save 和类CrudRepository,总之没有找到。 Spring 使用SimpleJpaRepository 作为CrudRepository 的默认实现,如果它在您的上没有找到任何事务属性,它将使用SimpleJpaRepository 中指定的属性。

@Transactional
public <S extends T> S save(S entity)

@Transactional 上的默认传播是必需的。

Propagation propagation() default Propagation.REQUIRED;

支持当前事务,如果不存在则创建一个新事务。

从上面的文档中可以看出,如果没有指定交易,它将创建一个新交易。因此,当您将业务层上的事务设置为NOT_SUPPORTED(非事务性执行)时,实际的CrudRepository 确实创建了它自己的事务,这意味着回滚不会影响它。

【讨论】:

  • 您好,感谢您的回答。这对我来说很有意义,我会尝试。你能解释一下为什么Propagation.NOT_SUPORTED 有效吗?
  • 它确实有效!谢谢!我真的需要更多地了解事务如何与 spring/jpa 一起工作。如果有文章请推荐。非常感谢!
  • Propagation.NOT_SUPORTED 有效,因为它基本上“说”:此方法不会在事务中运行。因此,当抛出异常时,spring 并没有回滚任何成功的操作。 Rentius 的回答非常有意义(毕竟它起作用了!)。以前没有意识到这个问题,我觉得有点愚蠢。
  • @VitorSantos spring 的默认设置是在单个事务中运行任何方法?我问是因为我没有 @Transactional 注释并且正在发生这个问题。
  • 您正在使用弹簧靴。我需要确定你的代码,但是很有可能在自动配置或类似的东西中设置事务。
猜你喜欢
  • 1970-01-01
  • 2017-02-06
  • 1970-01-01
  • 1970-01-01
  • 2021-01-21
  • 2013-04-29
  • 2016-03-18
  • 2011-03-03
  • 2021-12-05
相关资源
最近更新 更多