没有可用于当前线程的实际事务的EntityManager - 无法可靠地处理'删除'电话,例外

时间:2017-04-14 09:17:43

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

需要保存数据列表。在保存之前必须删除现有数据并保存新数据。 如果有任何删除&保存失败,该事务需要回滚,其余的删除&保存交易应该继续。

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

此处将为每个删除&amp;添加新的交易。保存

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

在删除时会抛出异常&#34;由以下原因引起: javax.persistence.TransactionRequiredException:没有可用于当前线程的实际事务的EntityManager - 无法可靠地处理&#39;删除&#39;调用&#34;

我可以通过为公共LabResResponse saveLabResult(List invstResults)方法添加@Transactional来解决这个问题。 但是我的初始用例将不起作用,这将回滚整个事务列表。

2 个答案:

答案 0 :(得分:2)

这是两个问题。

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

第二个问题是Spring(再次使用AspectJ)不能代理非公共方法。

摘要:以某种方式公开deleteResult方法并使用代理方法。作为建议,请使用另一个deleteResult组件。

答案 1 :(得分:0)

您正在捕获for循环中的异常,而您的要求表明您希望继续循环列表中的其他对象。 将你的try / catch块置于循环中。它应该工作正常

  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;

}