Java 如何在JPA中强制@Transactional提交两个存储库操作,而不仅仅是最后一个?
您好,我试图实现的是使用Spring数据JPA和@Transactional annotation执行“更新”操作,然后执行“删除”操作,我希望两个操作都执行,但如果其中一个操作失败,我需要回滚,我如何正确执行 首先是我的服务课:Java 如何在JPA中强制@Transactional提交两个存储库操作,而不仅仅是最后一个?,java,spring,jpa,spring-data-jpa,spring-transactions,Java,Spring,Jpa,Spring Data Jpa,Spring Transactions,您好,我试图实现的是使用Spring数据JPA和@Transactional annotation执行“更新”操作,然后执行“删除”操作,我希望两个操作都执行,但如果其中一个操作失败,我需要回滚,我如何正确执行 首先是我的服务课: @Transactional @Service public class TransDeliveryPlanningService { public ResponseRequest<TransDeliveryPlanning> deleteTra
@Transactional
@Service
public class TransDeliveryPlanningService {
public ResponseRequest<TransDeliveryPlanning> deleteTransDeliveryPlanning(InputDeleteRequest<ViewAndDeleteRequest> request) {
String currentUser = request.getLoggedInUser();
String reasonDeleted = request.getReason();
Long id = request.getObject().getId();
ResponseRequest<TransDeliveryPlanning> response = new ResponseRequest<TransDeliveryPlanning>();
TransDeliveryPlanning transDeliveryPlanningOld = transDeliveryPlanningRepository.findById(id).orElseThrow(() -> new ResourceNotFound("Data "+ id +" not found!"));
transDeliveryPlanningOld.setIsDeleted(true);
transDeliveryPlanningOld.setReasonDeleted(reasonDeleted);
transDeliveryPlanningOld.setModifiedBy(currentUser);
TransDeliveryPlanning updatedTransDeliveryPlanning = transDeliveryPlanningRepository.save(transDeliveryPlanningOld);
transDeliveryPlanningRepository.delete(transDeliveryPlanningOld);
//NOTE delete transStuffing
List<TransStuffing> transStuffing = transStuffingRepository.findBydeliveryPlanningId(transDeliveryPlanningOld.getId());
Boolean deletePermit = false;
for(TransStuffing ts : transStuffing) {
if(ts.getStatus().equalsIgnoreCase("new")) {
deletePermit = true;
} else {
throw new ResourceIsDelete("Stuffing " + ts.getStuffingNo() + " Status already changed, delete is not permited!");
}
}
if(deletePermit){
transStuffingRepository.deleteAll(transStuffing);
}
//NOTE end of delete transStuffing
if(updatedTransDeliveryPlanning != null) {
response.setResponse("Sukses Hapus");
response.setObject(updatedTransDeliveryPlanning);
} else {
response.setResponse("Gagal Hapus");
}
return response;
}
}
当我这样做时,它仍然不是在删除之前更新,我还遗漏了什么?尝试将
@Transactional
放在服务
方法中的方法上方。e、 g:
@Service
public class MyService {
@Autowired
private MyRepo myRepo;
@Autowired
private MyRepo2 myRepo2;
@Transactional
public void yourTransactionService(arguments){
*** your DML operations here ***
e.g.
myRepo.save(blabla);
myRepo.delete(blabla1);
...
myRepo2.save(blabla2);
myRepo3.delete(blabla3);
...
}
}
调用
yourTransactionService(arguments)
时,使用这种方法可以持久化所有的DML
或它们都不持久化。有一种简单的方法,只需使用查询本身,就可以使用提交、事务和回滚
例如:您必须首先启动事务,然后需要将autocommit设置为0,以便在您对所有操作都满意后,将发生的每个事务都不会得到commit,否则您可以将语句传递为rollback这将回滚启动事务后所做的所有操作。为了更好地理解这一点,请使用以下这是相同的结果,在myRepo.save(更新数据)中将不会执行,jpa直接执行myRepo.delete,有什么想法吗?在保存(更新)方法上方是否有修改?没有,my.save(object)函数是默认的jpa存储库函数,因此,我的存储库界面中没有@Modifying anotation。我也有同样的问题,这个答案以前对我有帮助:。因此,我必须定义own.save()函数并使用注释修改和查询,然后定义我自己的更新查询。你能帮我编写示例代码吗?链接是针对mysql的,我使用的是JPA Hibernate,我应该尽可能避免SQL查询层中的代码,如果问题可以通过JPA解决,我应该使用JPAIf。如果我正确理解,您需要首先更新一条记录,然后删除它,如果两个操作都可以,那么提交它们,否则回滚?看到你的代码,我觉得还可以。您启用了spring annotation事务管理吗?是的,我这样做是因为我需要创建审核日志数据,即我存储更新事件,然后是删除事件,是的,我通过将其添加到类的顶部来启用它,这是@Transactional的正确实现吗?我更喜欢在每个方法上放置
@Transactional
,而不是od类。通过启用spring事务管理,我的意思是尝试在spring配置类上添加注释@EnableTransactionManagement
ohh,我没有放置该注释,也没有spring配置类,或者你指的是用@SpringBootApplication注释的主类,我必须放@EnableTransactionManagement?我通常有一个DB的配置类(我很老了,我喜欢控制:),在这个配置类上我添加了注释。我从没试过把它放在主课上。。你可以试试
@Service
public class MyService {
@Autowired
private MyRepo myRepo;
@Autowired
private MyRepo2 myRepo2;
@Transactional
public void yourTransactionService(arguments){
*** your DML operations here ***
e.g.
myRepo.save(blabla);
myRepo.delete(blabla1);
...
myRepo2.save(blabla2);
myRepo3.delete(blabla3);
...
}
}