使用Spring Data JPA捕获SQL异常

3
以下方法尝试将数据写入DB(firmRepository.save())和ElasticSearch(firmSearchRepository.save())。
问题在于,如果DB保存失败,我不想写入ES存储库。我尝试使用DataAccessException捕获异常,但通过我的测试,我发现诸如唯一约束违规之类的异常仍然会传递,并且ElasticSearch中的持久性仍然会执行。
@Override
public FirmDTO save (FirmDTO firmDTO) {
    log.info("Database Request to save Firm: {}", firmDTO.getFirmId());
    Firm firm = firmMapper.firmDTOtoFirm(firmDTO);
    try {
        firm = firmRepository.save(firm);
        firmSearchRepository.save(firm);
        return firmMapper.firmToFirmDTO(firm);
    } catch (DataAccessException ex) {
        log.error(ex.getLocalizedMessage());
        return null;
    }
}

有没有办法捕获与SQL相关的特定异常?

5
是的,但只有在提交事务并完成刷新后,才能确定已保存某些内容。因此,您应该在尝试调用启动事务、数据库保存和提交事务方法的代码块中进行异常捕获(即使用try块)。 - JB Nizet
@JBNizet,你如何使用Spring Data JPA接口方法(例如.save())来实现这个功能? - Deniss M.
2
无论您是否使用spring-data-jpa都不重要。您有一个事务性方法,并且需要在此事务性方法调用成功并提交事务后保存到ES中。而不是在该事务性方法内部保存。无论您是否在该事务性方法内部使用spring-data-jpa都不重要。 - JB Nizet
@JBNizet 您误解了spring-data-jpa的概念。 - Deniss M.
3
嗯,不,我并不是。但如果你觉得相信这个可以让你感到舒适的话,那也没有关系。 - JB Nizet
这里的问题在于:工作单元没有明确定义。根据您的原始要求,您应该将所有与存储库保存相关的活动放在一个工作单元中。之后执行ES保存活动。然后一切都清晰而且具有事务性。 - Chi Cuong Le
1个回答

9
使用saveAndFlush() JPA仓库方法,可实现捕获Spring Data异常。
@Override
    @Transactional
    public FirmDTO save (FirmDTO firmDTO) {
        log.info("Database Request to save Firm: {}", firmDTO.getFirmId());
        Firm firm = firmMapper.firmDTOtoFirm(firmDTO);
        try {
            firm = firmRepository.saveAndFlush(firm);
            firmSearchRepository.save(firm);
            return firmMapper.firmToFirmDTO(firm);
        } catch (DataAccessException ex) {
            log.error("my exception");
            log.error(ex.getLocalizedMessage());
            return null;
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接