Jpa中的respository.save方法遭遇异常无法捕捉的场景

问题:

系统管理模块中采用了大量的缓存,系统初始化时,会从数据库中全量查询所有用户,部门等信息,缓存采用了二级缓存,使用ehcache作为本地一级缓存,redis作为集中式缓存,供其他服务调用,每当用户更新时,会通过xxxRespository.save()方法持久化到db,执行成功后,执行缓存,关键代码如下:

 @Override
 public Long create(UserPO userPO) {
        UserPO savedPO =  userDORepository.save(userPO);
        // 2.update cache
        userCache.put(new Element(savedPO.getId(), savedPO));
        return savedPO.getId();
    }

整个service层是配置了@Transactional的,过程中发现,如果在执行save时出现异常,比如主键唯一性冲突,

    @Override
 public Long create(UserPO userPO) {
        UserPO savedPO;
        try {
            savedPO = userDORepository.save(userPO);
        }catch (DataAccessException e){
            throw new BusinessException(e.getMessage());
        }
        
        userCache.put(new Element(savedPO.getId(), savedPO));
        return savedPO.getId();
    }

尝试使用DataAccessException捕捉该异常无果,追源码发现程序会在整个方法运行完时,DB层才会作整体事务的commit,此时,缓存其实建立,而数据库层面其实更新失败,导致缓存与数据库数据不一致的bug
解决方法:
数据库层面即时提交并检查,jpa中会我们提供了不同于savesaveAndFlush方法,此时,便可以正常捕获数据库层面的异常;

    @Override
 public Long create(UserPO userPO) {
        UserPO savedPO;
        try {
            savedPO = userDORepository.saveAndFlush(userPO);
        }catch (DataAccessException e){
            throw new BusinessException(e.getMessage());
        }
        //TODO  2.update cache
        userCache.put(new Element(savedPO.getId(), savedPO));
        return savedPO.getId();
    }

你可能感兴趣的:(Jpa中的respository.save方法遭遇异常无法捕捉的场景)