当前位置: 首页 > 知识库问答 >
问题:

当前线程没有实际事务可用的EntityManager-无法可靠地处理“remove”调用,异常

钱雅逸
2023-03-14

列出需要保存的数据。保存前必须删除现有数据并保存新数据。如果有任何删除

public LabResResponse saveLabResult(List<LabResInvstResultDto> invstResults) {
    LabResResponse labResResponse = new LabResResponse();
    List<Long> relInvstid = new ArrayList<Long>();
    try{
    if(invstResults != null){
        List<LabResInvstResult> labResInvstResults = mapper.mapAsList(invstResults, LabResInvstResult.class);
        for(LabResInvstResult dto: labResInvstResults){
            if(dto != null){
                //delete all child records before save. 
                deleteResult(dto, relInvstid);
            }
        }
    }
    labResResponse.setRelInvstids(relInvstid);

    }catch(Exception e){
        e.printStackTrace();
    }
    return labResResponse;
}

在这里,每次删除都会添加新事务

@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = { Exception.class })
private void deleteResult(LabResInvstResult dto, List<Long> relInvstid) {
    try{
        labResultRepo.deleteById(dto.getId());          
        LabResInvstResult result = labResultRepo.save(dto);

    }catch(Exception e){
        e.printStackTrace();
    }
}

在删除时,它会引发异常“由以下原因引起:javax.persistence.TransactionRequiredException:没有具有实际事务的实体管理器可用于当前线程 - 无法可靠地处理'remove'调用”

我可以通过添加一个@ Transactional for public labresponse savelab result(List invstResults)方法来解决这个问题。但是我最初用例不起作用,这将回滚整个事务列表。

共有2个答案

昝枫
2023-03-14

您正在从 for 循环中捕获异常,而您的要求说您希望继续列表中其他对象的循环。将尝试/捕获块与 in 循环。它应该工作正常

  public LabResResponse saveLabResult(List<LabResInvstResultDto> invstResults) {
LabResResponse labResResponse = new LabResResponse();
List<Long> relInvstid = new ArrayList<Long>();
try{
if(invstResults != null){
    List<LabResInvstResult> labResInvstResults = mapper.mapAsList(invstResults, LabResInvstResult.class);
    for(LabResInvstResult dto: labResInvstResults){
        if(dto != null){
            //delete all child records before save. 
               try {
            deleteResult(dto, relInvstid);
             } catch(Exception e){
                 e.printStackTrace();
             }
        }
    }
}
labResResponse.setRelInvstids(relInvstid);

}catch(Exception e){
    e.printStackTrace();
}
return labResResponse;

}

饶曦之
2023-03-14

这里有两个问题。

第一个问题是您调用类的“real”deleteResult方法。当Spring看到@Transactional时,它会创建一个具有事务行为的代理对象。除非您使用的是AsheJ,否则它不会更改类本身,而是创建一个新的代理。因此,当您自动配置此bean时,您将能够使用运行与事务相关逻辑的代理方法。但在您的情况下,您引用的是类的方法,而不是代理。

第二个问题是Spring(同样如果不使用AsheJ)不能代理非公共方法。

摘要:以某种方式使< code>deleteResult方法成为公共方法,并使用代理方法。建议使用另一个带有< code>deleteResult的组件

 类似资料: