【发布时间】:2021-06-06 08:30:24
【问题描述】:
我想知道在以下情况下推荐的操作方式是什么:
- 假设我有一个
ReportService负责生成报告、上传报告、发送电子邮件并将其保存到数据库中。 - 在数据库中保存时,它会更新很多实体,我想回滚整个内容以防出现故障。
所以应该是这样的:
@Service
public class ReportService {
public void generateReport() {
var entities = entityRepository.findEntities();
var file = getReportData(entities);
var url = uploadFile(file);
sendEmail(url);
// If something goes wrong while save on entity, roll back everything
for (var e : entities) {
entityRepository.save(e);
}
}
}
所以我知道我有以下选择:
- 使用
@Transactional注释该方法:我认为这不是一个好主意,因为我们会将 HTTP 请求和工作负载与数据库事务混合在一起 - 创建一个全新的服务,例如
ReportSavingService,并使用一种方法来仅保存这些实体:我认为这可行,但对我来说,处理与我已经拥有的相同业务逻辑的特定服务似乎很奇怪服务,只是为了保存它......
我想知道这些是否是我们处理 Spring Data 的解决方案,或者是否有一种简单的方法可以执行以下操作:
// ...
sendEmail(url);
// If something goes wrong while save on entity, roll back everything
database.beginTransaction();
for (var e : entities) {
entityRepository.save(e);
}
database.commit();
我知道我们的这种控制有点下降,直接使用EntityManager,但是我不能将它与 Spring Data 的存储库方法混合...我可以吗?
【问题讨论】:
-
好吧,你可以注入
TransactionTemplate并使用transactionTemplate.execute(...),但我建议重新考虑设计 - 请注意,当你首先运行不可逆操作时(发送电子邮件) ,总是存在执行永远不会到达持久性代码的风险。更好的方法是生成报告,将其保存到数据存储中,然后仅在事务成功后发送电子邮件(或者,更好的是,有一个单独的工作来通过电子邮件发送待处理的报告) -
谢谢@crizzis,是的,我同意你的观点。这实际上不是一个真实的案例,只是一个例子:) 看看
TransactionTemplate,不知道:D
标签: java spring-boot spring-data-jpa transactions