春季-跨多个服务和存储库的@Transactional

时间:2019-09-16 23:47:41

标签: hibernate spring-boot spring-data-jpa spring-transactions

我正在使用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
}

在数据库中,目标,公差,最大值和成分的表都具有对MasterSpec表的外键引用,因此我最后删除了MasterSpec。

我希望MasterSpecService是主要交易,并让所有其他服务附加到该交易中,因此,如果发生任何故障,它将还原。所有服务都有自己的JPA信息库来处理删除操作。

是否可以通过@Transactional注释来完成?

或者,当我在MasterSpec记录上调用delete时,如果事务的任何部分失败了,将在我的各个Entity类中使用@OneToMany和@ManyToOne映射完成相同的任务并还原所有已删除的记录吗?

1 个答案:

答案 0 :(得分:0)

经过进一步的挖掘,就像我在问题末尾提到的那样,一种更合适的方法是在类上使用带有@ OneToOne,@ OneToMany和@ManyToOne批注的双向映射。

在我的Entity类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,PReceivingTolerance,PFinishedGoodTarget,PFinishedGoodTolerance,PMaxValue实体类中,我通过外键映射回了PMasterSpec类:

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

在PIngredient类中:

@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对象并提供所有其他嵌套的实体类,当我调用masterspecRepo.save(masterSpec)时,它将创建单个事务来保存所有实体对象,并在保存或删除时回滚所有内容发生问题。

我遵循以下示例:

Spring Boot JPA One to Many Mapping

Spring Boot JPA One to One Mapping