有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何在JPA中强制@Transactional提交两个存储库操作而不仅仅是最后一个?

您好,我试图实现的是使用Spring数据JPA和@Transactional annotation执行“更新”操作,然后执行“删除”操作,我希望两个操作都执行,但如果其中一个操作失败,我需要回滚,我如何正确执行

首先是我的服务课:

@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;
    }

}

如您所见,我执行transDeliveryPlanningRepository.save,然后执行下一行transDeliveryPlanningRepository.delete,我需要执行的下一次回购是transStuffingRepository.deleteAll

我需要在删除之前保存的目标是使用Hibernate Audit Envers创建一个AuditLog,因此我希望将删除原因记录到我的Audit表中,然后删除记录。但是当我使用**@Transactional**注释时,transDeliveryPlanningRepository.save(更新)没有执行,我的函数只是执行transDeliveryPlanningRepository.deletetransStuffingRepository.deleteAll如何使用@Transactional annotation保持保存执行

更新

正如Morteza Bandi回答以下建议,以下是我的更新代码: 这是我的存储库:

@Repository
public interface TransDeliveryPlanningRepository extends RevisionRepository<TransDeliveryPlanning, Long, Integer>, JpaRepository<TransDeliveryPlanning, Long> {
    
    @Modifying
    TransDeliveryPlanning save(TransDeliveryPlanning transDeliveryPlanning);
}

当我这样做的时候,它仍然没有在删除之前更新,我仍然错过了什么


共 (2) 个答案

  1. # 1 楼答案

    尝试将@Transactional放在service方法内的方法上方。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都被持久化,要么没有一个被持久化

  2. # 2 楼答案

    有一种简单的方法可以做到这一点,只需使用查询本身,就可以使用提交、事务和回滚

    例如:您必须首先启动事务,然后需要将autocommit设置为0,以便在您对所有操作都满意后,将发生的每个事务都不会得到commit,否则您可以将语句传递为rollback这将回滚启动事务后所做的所有操作。为了更好地理解这一点,请使用以下link