主线程做删除子线程还能查到数据

情况: 我在主线程中做了一个删除操作,但是在子线程中还能查到,我使用了事务,并且还设置了事务的传播级别,可是还是不行。但通过询问大牛,我找到了以下几种方法:

1.方法一:在子线程的查询语句中使用 for update 。(未尝试)
for update是一种行级锁,又叫排它锁,一旦用户对某个行施加了行级加锁,则该用户可以查询也可以更新被加锁的数据行,其它用户只能查询但不能更新被加锁的数据行.如果其它用户想更新该表中的数据行,则也必须对该表施加行级锁.即使多个用户对一个表均使用了共享更新,但也不允许两个事务同时对一个表进行更新,真正对表进行更新时,是以独占方式锁表,一直到提交或复原该事务为止。行锁永远是独占方式锁。

2.方法二:在主线程删除后直接提交。


```java
 @Transactional
    public void onlineConfirmImport(MultipartFile file, Integer agencyAgreementType, String importYear) {
    
    
        String errorImport = "导入模板不正确";
        // 获取上传数据
        List<OnlineConfirmImportVO> loadExcelData = loadExcelData(file, agencyAgreementType);
        //手动获取事务状态
        TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
        //删除旧的年份数据
        try {
    
    
            //通过agencyAgreementType importYear 查到对应的线上确认数据
            OnlineConfirmSearchDTO onlineConfirmSearchDTO = new OnlineConfirmSearchDTO();
            onlineConfirmSearchDTO.setAgencyAgreementType(agencyAgreementType);
            onlineConfirmSearchDTO.setImportYear(importYear);
            List<OnlineConfirm> yearList = onlineConfirmDao.getList(onlineConfirmSearchDTO);
            List<Long> ids = new ArrayList<>();
            List<String> agencyAgreementCodes = new ArrayList<>();
            yearList.forEach(onlineConfirm -> {
    
    
                ids.add(onlineConfirm.getId());
                agencyAgreementCodes.add(onlineConfirm.getAgencyAgreementCode());
            });
            if(!ids.isEmpty()) {
    
    
                onlineConfirmDao.deleteByIds(ids);
            }
            if (!agencyAgreementCodes.isEmpty()) {
    
    
                onlineManualDao.deleteByAgencyAgreementCodes(agencyAgreementCodes);
            }
            transactionManager.commit(transactionStatus);
        }catch (Exception e){
    
    
            transactionManager.rollback(transactionStatus);
            throw  new BusinessException("导入失败,数据异常");
        }

        //创建子线程去做操作...
     
    }

3.方法二的优化。
在方法二中,我们删除完是直接提交事务的,但是我们在子线程或者是后续的业务中可能会出现异常,这时我们的数据都提交了,就相当于我们啥都没做直接把数据给他删了,这样是不对的。
所以我们在删除的时候,可以先不做物理删除,我们先给他做一个逻辑删除,同时使用ThreadLocal去保存这些被删除的数据。使用 try -catch -finally,若是出现异常,我们在catch中手动update这些数据让他还原;若是没有出现异常,我们再在finally里取出ThreadLocal中的那些数据,将他们真正的逻辑删除。

猜你喜欢

转载自blog.csdn.net/weixin_45933454/article/details/127068104
今日推荐