【问题标题】:Spring Data Jpa - Repository doesn't thrown exception when @transactional existsSpring Data Jpa - 当@transactional存在时存储库不会抛出异常
【发布时间】:2023-03-13 01:29:01
【问题描述】:

我有以下课程:

public interface GarageRepository extends PagingAndSortingRepository<Garage, Integer> {}

public class GarageBO {
  private GarageRepository garageRepository;

  public void updateGarage(Garage garage) {
    try {
      garageRepository.save(garage);
    } catch (Exception e) {
      throw BoozinaExceptions.getCodeException(garage, e);
    }
  }
}

public class GarageFacade implements GarageService {
  private GarageBO garageBO;

  @Transactional
  public void updateGarage(Garage garage) {
    garageBO.updateGarage(garage);
  }
}

假设我正在尝试更新车库并且引发了独特的违规行为。
当我使用 @Transactional 注释从 GarageFacade 调用 updateGarage 时,garageRepository 不会引发任何异常。
当我在没有 @Transactional 注释的情况下调用相同的方法时,garageRepository 会抛出唯一的违规异常,现在我可以使用 BoozinaExceptions.getCodeException(garage, e) 转换异常;

发生这种行为是因为当我有@Transactional 注释时,Spring jpa 数据执行提交时将引发异常。这发生在 GarageBO.updateGarage 执行 ok 之后?

但我需要转换唯一违规。我该怎么做?
提交后如何处理spring异常然后转换为我的异常?

【问题讨论】:

  • 当车库实体不存在并且我尝试保存它时,catch 块被执行并且我可以转换异常。但是当车库实体已经存在时,catch 块不会被执行,并且休眠日志中会出现这一行:HHH000010: On release of batch it still contains JDBC statements

标签: spring hibernate jpa spring-data-jpa


【解决方案1】:

您所描述的是预期的行为。方法结束后提交事务,提交导致违反唯一约束。

在服务方法中添加@Transactional 使事务在调用服务方法后事务被提交。删除它会使事务在调用存储库方法后提交。

还有为什么你有一个 BO 一个 Facade 和一个 Repository?!基本上 BO 和 Facade 是相同的恕我直言。

要解决您的问题,请使用您的 GarageRepository 扩展 JpaRepository 而不是 PagingAndSortingRepository 并调用 saveAndFlush 方法而不是 save。这将执行sql(不提交事务)并触发约束冲突异常。

另一种解决方案是不要在您的 BO 创建和执行转换的 Aspect 中执行 try/catch。每次需要时都可以节省您对 try/catch 的编码。

【讨论】:

  • 我有一个 BO 和 Facabe,因为一个外观可以与多个 BO 实体交互。示例:GarageFacade 有一个 GarageBO 和 MessageBO,因为当我创建一个 Garage 时,我会创建实体 Garage 并使用 MessageBO 发送一封电子邮件。但我也可以在不发送电子邮件的情况下创建车库,或者我可以在不创建车库的情况下发送电子邮件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-08
  • 1970-01-01
  • 2017-09-08
  • 1970-01-01
  • 1970-01-01
  • 2021-10-11
  • 2018-08-06
相关资源
最近更新 更多