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 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)
时,它将创建一个事务来保存所有实体对象,并且如果出现问题,回滚保存或删除的所有内容。
我遵循了这些例子: