针对业务的SQL优化

自己写代码的时候有时候会琢磨如何写的好一点,然后某一天灵感来了就记录一下。(才入职没多久)主要是分享一下思路。

业务需求:导入的员工的Excel数据,导入以后需要和数据库里面的进行比对,以及对excel里面的数据进行一个校验,如果存在就修改,不存在就新增。

未优化的代码:(部分代码,这个不是我写的)

  for (UserExcel user : userExcels) {
SpringContextUtils.getBean(StaffStandardMapper.class).selectOne(Wrappers.<StaffStandard>lambdaQuery()
                            .eq(StaffStandard::getPhoneNum, req.getPhoneNum())
                            .eq(StaffStandard::getStaffNumber, user.getStaffNumber()));
   // 保存用户详情
b = standardService.saveUserDetail(staff, req, redisUser);
b = saveOrUpdateProftitles(user.getHonorName(), staff.getStaffId());
isysuserservice.update(Wrappers.<SysUser>lambdaUpdate().set(SysUser::getIsForbidden, 1).eq(SysUser::getStaffId, staff.getStaffId()));
isysuserservice.update(Wrappers.<SysUser>lambdaUpdate().set(SysUser::getIsForbidden, 0).eq(SysUser::getStaffId, staff.getStaffId()));
}

可以看到在循环里面对数据库进行多次连接操作。
下面和上面是两个业务接口


优化后的代码:

    Map<String, Integer> socialAgency = socialAgencyConfigService.getSocialAgencyConfigs().stream().collect(Collectors.toMap(SocialAgencyConfig::getSocialAgencyName, SocialAgencyConfig::getSocialAgencyId));
        Map<String, Integer> paymentName = paymentMethodBaseMapper.getPaymentName().stream().collect(Collectors.toMap(PaymentMethodBase::getPaymentMethodName, PaymentMethodBase::getPaymentMethodId));
        List<Integer> staffIds = excels.stream().map(e -> extractIdFromStaffNumber(e.getStaffNumber())).collect(Collectors.toList());
        Map<Integer, StaffStandard> staffStandardMap = staffStandardMapper.selectList(Wrappers.<StaffStandard>lambdaQuery().in(StaffStandard::getStaffId, staffIds).select(StaffStandard::getStaffId)).stream().collect(Collectors.toMap(StaffStandard::getStaffId, staffStandard -> staffStandard));
        Map<Integer, StaffDetail> staffDetailMap = detailService.list(Wrappers.<StaffDetail>lambdaQuery().in(StaffDetail::getStaffId, staffIds).select(StaffDetail::getStaffId).select(StaffDetail::getPersonId)).stream().collect(Collectors.toMap(StaffDetail::getStaffId, staffDetail -> staffDetail));

主要思路:能批量处理的就一次性处理,这里我是拿到需要查询的主键一次性把后面Excel里面需要比对的数据从数据库里查出来,相当于是把数据库的数据存到JVM内存。存储为Map,以员工ID为主键,员工信息为value。主要是后面在比对的时候可以直接根据ID拿到查出来的员工信息。

然后针对校验通过的员工Excel数据,需要在数据库里修改,这里我直接把需要修改的员工信息单独存在一个集合里面,然后直接一个批量修改。代码如下;
 

        LinkedHashSet<StaffStandard> successStaffStandards = new LinkedHashSet<>();
        successStaffStandards.add(staffStandard);
        this.updateBatchById(successStaffStandards);

这么做的话就不用每一次循环都去操作数据库很多次,减少了操作数据库次数。


思路分享:

1、能批量处理的尽可能批量处理,减少在循环中对数据库的操作。
2、查询时尽量只查出需要的字段,没用的字段不用查出。
3、一次性把需要的数据查出来,然后在服务层进行一个数据处理。
3、如果一次性查出来的数据太多,可能会导致内存溢出,这种情况可以进行一个分页查询,分批次进行一个处理。

如果对你有用的话点一个赞吧! 

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

麋鹿会飞但不飘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值