Spring boot @Transactional 不回滚数据库插入

Bha*_*v J 6 java spring-transactions spring-boot

这里需要一些帮助,我无法理解为什么我的事务在发生异常时不会回滚。

我会尝试将我的代码尽可能接近项目中的位置(无法在互联网上共享)

这是我的服务

@Service
@SL4j
@Transactional(propagation = propagation.SUPPORTS, readOnly=true)
public class PublicationServiceImpl implements PublicationService{
    @Autowired 
    private PartnerRepo partnerRepo;
                
    @Autowired
    private FlowRepo flowRepo;

    @Autowired
    private PubRepo pubRepo;
                
    @Override
    @Transactional(propagation = propagation.REQUIRED, rollbackFor=Exception.class)
    public int save(Request request) {
    try{
                   int  pk_id_partner = partnerRepo.save(request);
                   int  pk_id_flow = flowRepo.save(request);
        
                   String publicationCode = generatePubCode(request);
                   int publicationCode= pubRepo.save(pk_id_partner, pk_id_flow, request);
        }
        catch(Exception e){
        log.error("Exception in saving");
    }
    return 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的存储库(1 的示例,所有 3 个存储库都遵循相同的编码标准)

@Repository
@Slf4j
public class PartnerRepo implemets PartnerRepo{
    @Autowired
    private NamedParamaterJDBCTemplate namedParamaterJDBCTemplate;
    //String Declarations .....

    private MapSqlParameterSource sqlParameterSource;

    @Override
    public int save(Request request){
        sqlParamatersSource = new MapSqlParameterSource();
        //sqlParamatersSource.addValue(.....)
        //sqlParamatersSource.addValue(.....)
        //sqlParamatersSource.addValue(.....)

        return executeQuery();
    }

    private int executeQuery(){
        try{
            keyHolder = new GenerateKeyHolder();
            namedParamaterJDBCTemplate.update(getInsertQuery(), sqlParamaterSource , kekHolder, new String[]{"pk_id"})
            return keyHolder.getKey().intValue();
        }catch(Exception e){
            log.error("Exception while saving");
            return 0;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

那么问题来了,考虑到方法中存在异常generatePubCode(request);,理想情况下由于我在类级别和方法级别都使用过@Transactional,之前的2个repo transactions()应该回滚吧?然而它并没有发生,即使代码完成执行后我也可以看到数据库(Postgres DB v10)中的记录。

请帮忙解决这个问题,我是不是做错了什么?

如果您需要更多可能有帮助的信息,请告诉我!

PS:我已经尝试了 的所有排列@Transactional,但没有任何效果:只有在 catch 块中使用它才有效! TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 我想知道这对于 springBoot 项目是否是正确的方法

先谢谢您的帮助!

编辑:根据公开的PublicationServiceSaverImpl.save()建议

最好的问候,巴尔加夫。

M. *_*num 8

有几件事会破坏 Spring 中的正常事务

  1. 您的服务方式是private
  2. 你正在捕获并吞掉异常

private方法

事实上,你的PublicationServiceImpl save方法private基本上使得@Transactional该方法毫无用处。由于private方法无法被代理,因此不会应用任何交易。即使是这样,当public您从同一对象内调用该方法时,它也不会起作用,因此该方法的事务性适用。

要修复此问题,请创建您的方法publicsave从其他类调用该方法(或者使正在调用的实际方法save具有正确的@Transactional.

事实上,这是行不通的,因为使用了 op AOP 类型,默认情况下 Spring 将使用代理,这是使用基于代理的 AOP 的一个缺点。

使其与private方法一起使用的另一个解决方案是切换到成熟的 AspectJ,并通过类的编译时或加载时编织来实现。两者都需要额外的设置,而且可能很乏味。

捕获并吞掉异常

您的存储库和服务中都有一个try/catch块。其中每一个都会捕获并吞掉异常(它们被记录但不会重新抛出)。

为了使事务正常工作,需要查看异常情况。事实上,您捕获并吞下它们,使得事务方面看不到它们,并且不进行回滚,而是进行提交。对于交易方面,一切都很好,因为没有例外。

要修复此问题,请删除异常try/catch或重新引发异常。


Sor*_*iuc 7

由于 Spring 中代理的创建方式,注释通常不适用于从同一类调用的方法。

它与 @Transaction 特别无关,但与您的方法是私有的并且从同一对象内调用这一事实有关。

请将方法公开,并将 @Transactional 方法移动到用 @Service 注释的单独类中,并从类实例的外部调用它

  @Service
  public class PublicationServiceSaverImpl {

     @Transactional
     **public** int save(Request request) {
      ...
     }
  }
Run Code Online (Sandbox Code Playgroud)

您必须从 PublicationServiceSaverImpl 类的外部调用 save 方法,也许是从 PublicationServiceImpl 调用。