Spring - @Transactional 跨多个服务和存储库

Spring - @Transactional across multiple services and repositories

我正在使用 Spring Boot v2.1.3.RELEASE 和 Hibernate v5.3.6.

构建应用程序

我希望完成的是在我的服务上使用@Transactional 注释来确保在删除记录时,如果发生错误,无论是数据库异常还是业务逻辑异常,事务中删除的任何记录都将回滚到删除开始前的原始状态。

我希望交易开始的服务是 MasterSpecService 并像这样调用其他服务:

deleteMasterSpec(MasterSpec masterSpec) {
     this.approvalTargetService.deleteApprovalTargetsForSpec(masterSpec.getSysI());
     this.approvalToleranceService.deleteApprovalTolerancesForSpec(masterSpec.getSysI());
     this.receivingToleranceService.deleteReceivingTolerancesForSpec(masterSpec.getSysI());
     this.finishedGoodTargetService.deleteFinishedGoodTargetsForSpec(masterSpec.getSysI());
     this.finishedGoodToleranceService.deleteFinishedGoodTolerancesForSpec(masterSpec.getSysI());
     this.maxValueService.deleteMaxValuesForSpec(masterSpec.getSysI());
     this.ingredientService.deleteSpecIngredients(masterSpec.getSysI());
     this.masterSpecRepo.deleteById(masterSpec.getSysI()); 
     // throw some exception here as a test, and have all the deletes rollback
}

在数据库中,tables 的目标、公差、最大值和成分都有对 MasterSpec table 的外键引用,所以我最后删除了 MasterSpec。

我希望 MasterSpecService 成为主要事务,并让所有其他服务附加到该事务,因此如果任何失败,它将恢复。所有服务都有自己的 JPA 存储库来处理删除。

这可以用@Transactional 注释来完成吗?

或者,在我的各种实体中使用@OneToMany 和@ManyToOne 映射 类 是否可以完成相同的任务并在我对 MasterSpec 记录调用 delete 时交易的任何部分失败时恢复任何已删除的记录?,

经过更多的挖掘,我在问题结尾提到的更合适的方法是在我的 classes 上使用带有 @OneToOne、@OneToMany 和 @ManyToOne 注释的双向映射。

在我的实体 class PMasterSpec.java 中,我添加了:

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "masterSpec")
private PApprovalTarget approvalTarget;

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "masterSpec")
private PApprovalTolerance approvalTolerance;

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "masterSpec")
private PReceivingTolerance receivingTolerance;

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "masterSpec")
private PFinishedGoodTarget finishedGoodTarget;

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "masterSpec")
private PFinishedGoodTolerance finishedGoodTolerance;

@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "masterSpec")
private PMaxValue maxValue;

@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "masterSpec")
private List<PIngredient> ingredients;

并且在 PApprovalTarget、PApprovalTolerance、PRecivingTolerance、PFinishedGoodTarget、PFinishedGoodTolerance、PMaxValue 实体 classes 中,我通过外键映射回 PMasterSpec class:

@OneToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "BOM_SPEC_SYS_I")
private PMasterSpec masterSpec;

并且在 PIngredient class:

@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "BOM_SPEC_SYS_I", insertable = false, updatable = false)
private PMasterSpec masterSpec;

我的 MasterSpecService 仍然被标记为事务性的:

@Transactional(propagation = Propagation.REQUIRED)

但所有其他服务都不是。

现在,只要我构建 PMasterSpec 对象并提供所有其他嵌套实体 classes,当我调用 masterspecRepo.save(masterSpec) 时,它将创建一个事务来保存所有实体对象,并且如果出现问题,回滚保存或删除的所有内容。

我遵循了这些例子:

Spring Boot JPA One to Many Mapping

Spring Boot JPA One to One Mapping