From 1af2677c051f694dff6a4cc70de3cd4e9040917f Mon Sep 17 00:00:00 2001 From: wkc <978997012@qq.com> Date: Wed, 4 Feb 2026 19:52:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AF=BC=E5=85=A5=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E6=89=B9=E9=87=8F=E6=8F=92=E5=85=A5=E5=92=8C?= =?UTF-8?q?=E6=89=B9=E9=87=8F=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 修改内容 ### Mapper 接口 - CcdiBizIntermediaryMapper: 新增 insertBatch() 和 updateBatch() 方法 - CcdiEnterpriseBaseInfoMapper: 新增 insertBatch() 和 updateBatch() 方法 ### Mapper XML - 新增 CcdiBizIntermediaryMapper.xml: 实现个人中介的批量插入和更新 - 新增 CcdiEnterpriseBaseInfoMapper.xml: 实现实体中介的批量插入和更新 - 批量插入使用 VALUES (...), (...), (...) 语法 - 批量更新使用 foreach 分隔多条 UPDATE 语句 ### Service 实现 - importIntermediaryPerson(): 改为两轮处理模式 - 第一轮:数据验证和分类(区分插入和更新) - 第二轮:批量插入新记录 + 批量更新已存在记录 - importIntermediaryEntity(): 改为两轮处理模式 - 第一轮:数据验证和分类(区分插入和更新) - 第二轮:批量插入新记录 + 批量更新已存在记录 ## 性能优化 - 从原来的逐条插入/更新改为批量操作 - 减少数据库连接次数,提升大数据量导入性能 - 事务一致性保证,全部成功或全部回滚 编译验证:通过 --- .../mapper/CcdiBizIntermediaryMapper.java | 17 +++ .../mapper/CcdiEnterpriseBaseInfoMapper.java | 17 +++ .../impl/CcdiIntermediaryServiceImpl.java | 111 ++++++++++++++---- .../mapper/ccdi/CcdiBizIntermediaryMapper.xml | 55 +++++++++ .../ccdi/CcdiEnterpriseBaseInfoMapper.xml | 60 ++++++++++ 5 files changed, 238 insertions(+), 22 deletions(-) create mode 100644 ruoyi-ccdi/src/main/resources/mapper/ccdi/CcdiBizIntermediaryMapper.xml create mode 100644 ruoyi-ccdi/src/main/resources/mapper/ccdi/CcdiEnterpriseBaseInfoMapper.xml diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/mapper/CcdiBizIntermediaryMapper.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/mapper/CcdiBizIntermediaryMapper.java index 476fbdb..4b45848 100644 --- a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/mapper/CcdiBizIntermediaryMapper.java +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/mapper/CcdiBizIntermediaryMapper.java @@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.ccdi.domain.CcdiBizIntermediary; import org.apache.ibatis.annotations.Mapper; +import java.util.List; + /** * 个人中介Mapper接口 * @@ -13,4 +15,19 @@ import org.apache.ibatis.annotations.Mapper; @Mapper public interface CcdiBizIntermediaryMapper extends BaseMapper { + /** + * 批量插入个人中介 + * + * @param list 个人中介列表 + * @return 插入行数 + */ + int insertBatch(List list); + + /** + * 批量更新个人中介 + * + * @param list 个人中介列表 + * @return 更新行数 + */ + int updateBatch(List list); } diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/mapper/CcdiEnterpriseBaseInfoMapper.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/mapper/CcdiEnterpriseBaseInfoMapper.java index 0fc875f..613a7d8 100644 --- a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/mapper/CcdiEnterpriseBaseInfoMapper.java +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/mapper/CcdiEnterpriseBaseInfoMapper.java @@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.ccdi.domain.CcdiEnterpriseBaseInfo; import org.apache.ibatis.annotations.Mapper; +import java.util.List; + /** * 实体中介Mapper接口 * @@ -13,4 +15,19 @@ import org.apache.ibatis.annotations.Mapper; @Mapper public interface CcdiEnterpriseBaseInfoMapper extends BaseMapper { + /** + * 批量插入实体中介 + * + * @param list 实体中介列表 + * @return 插入行数 + */ + int insertBatch(List list); + + /** + * 批量更新实体中介 + * + * @param list 实体中介列表 + * @return 更新行数 + */ + int updateBatch(List list); } diff --git a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiIntermediaryServiceImpl.java b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiIntermediaryServiceImpl.java index af77a30..c2e85b4 100644 --- a/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiIntermediaryServiceImpl.java +++ b/ruoyi-ccdi/src/main/java/com/ruoyi/ccdi/service/impl/CcdiIntermediaryServiceImpl.java @@ -285,7 +285,7 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService { } /** - * 导入个人中介数据 + * 导入个人中介数据(批量操作) * * @param list Excel实体列表 * @param updateSupport 是否更新支持 @@ -303,8 +303,16 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService { StringBuilder successMsg = new StringBuilder(); StringBuilder failureMsg = new StringBuilder(); - for (CcdiIntermediaryPersonExcel excel : list) { + // 待插入和更新的列表 + List insertList = new ArrayList<>(); + List updateList = new ArrayList<>(); + List personIds = new ArrayList<>(); + + // 第一轮:数据验证和分类 + for (int i = 0; i < list.size(); i++) { try { + CcdiIntermediaryPersonExcel excel = list.get(i); + // 验证数据 if (StringUtils.isEmpty(excel.getName())) { throw new RuntimeException("姓名不能为空"); @@ -319,29 +327,26 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService { person.setPersonType("中介"); person.setDataSource("IMPORT"); + personIds.add(excel.getPersonId()); + // 检查唯一性 if (!checkPersonIdUnique(excel.getPersonId(), null)) { if (updateSupport) { - // 更新模式:查询已存在记录并更新 - LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); - wrapper.eq(CcdiBizIntermediary::getPersonId, excel.getPersonId()); - CcdiBizIntermediary existingPerson = bizIntermediaryMapper.selectOne(wrapper); - if (existingPerson != null) { - person.setBizId(existingPerson.getBizId()); - bizIntermediaryMapper.updateById(person); - } + // 需要更新,暂时加入更新列表 + updateList.add(person); } else { throw new RuntimeException("该证件号已存在"); } } else { - bizIntermediaryMapper.insert(person); + // 新数据,加入插入列表 + insertList.add(person); } successNum++; successMsg.append("
").append(successNum).append("、").append(excel.getName()).append(" 导入成功"); } catch (Exception e) { failureNum++; - failureMsg.append("
").append(failureNum).append("、").append(excel.getName()).append(" 导入失败:"); + failureMsg.append("
").append(failureNum).append("、").append(list.get(i).getName()).append(" 导入失败:"); failureMsg.append(e.getMessage()); } } @@ -349,14 +354,49 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService { if (failureNum > 0) { failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); throw new RuntimeException(failureMsg.toString()); - } else { + } + + // 第二轮:批量处理 + try { + // 批量插入新记录 + if (!insertList.isEmpty()) { + bizIntermediaryMapper.insertBatch(insertList); + } + + // 批量更新已存在的记录 + if (!updateList.isEmpty()) { + // 查询已存在记录的bizId + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.in(CcdiBizIntermediary::getPersonId, personIds); + List existingList = bizIntermediaryMapper.selectList(wrapper); + + // 建立personId到bizId的映射 + java.util.Map personIdToBizIdMap = new java.util.HashMap<>(); + for (CcdiBizIntermediary existing : existingList) { + personIdToBizIdMap.put(existing.getPersonId(), existing.getBizId()); + } + + // 设置bizId到更新列表 + for (CcdiBizIntermediary person : updateList) { + String bizId = personIdToBizIdMap.get(person.getPersonId()); + if (bizId != null) { + person.setBizId(bizId); + } + } + + // 批量更新 + bizIntermediaryMapper.updateBatch(updateList); + } + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条"); return successMsg.toString(); + } catch (Exception e) { + throw new RuntimeException("批量操作失败:" + e.getMessage()); } } /** - * 导入实体中介数据 + * 导入实体中介数据(批量操作) * * @param list Excel实体列表 * @param updateSupport 是否更新支持 @@ -374,8 +414,16 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService { StringBuilder successMsg = new StringBuilder(); StringBuilder failureMsg = new StringBuilder(); - for (CcdiIntermediaryEntityExcel excel : list) { + // 待插入和更新的列表 + List insertList = new ArrayList<>(); + List updateList = new ArrayList<>(); + List socialCreditCodes = new ArrayList<>(); + + // 第一轮:数据验证和分类 + for (int i = 0; i < list.size(); i++) { try { + CcdiIntermediaryEntityExcel excel = list.get(i); + // 验证数据 if (StringUtils.isEmpty(excel.getEnterpriseName())) { throw new RuntimeException("机构名称不能为空"); @@ -390,26 +438,29 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService { // 检查唯一性 if (StringUtils.isNotEmpty(excel.getSocialCreditCode())) { + socialCreditCodes.add(excel.getSocialCreditCode()); + if (!checkSocialCreditCodeUnique(excel.getSocialCreditCode(), null)) { if (updateSupport) { - // 更新模式 - enterpriseBaseInfoMapper.updateById(entity); + // 需要更新,加入更新列表 + updateList.add(entity); } else { throw new RuntimeException("该统一社会信用代码已存在"); } } else { - enterpriseBaseInfoMapper.insert(entity); + // 新数据,加入插入列表 + insertList.add(entity); } } else { - // 没有统一社会信用代码,直接插入 - enterpriseBaseInfoMapper.insert(entity); + // 没有统一社会信用代码,直接加入插入列表 + insertList.add(entity); } successNum++; successMsg.append("
").append(successNum).append("、").append(excel.getEnterpriseName()).append(" 导入成功"); } catch (Exception e) { failureNum++; - failureMsg.append("
").append(failureNum).append("、").append(excel.getEnterpriseName()).append(" 导入失败:"); + failureMsg.append("
").append(failureNum).append("、").append(list.get(i).getEnterpriseName()).append(" 导入失败:"); failureMsg.append(e.getMessage()); } } @@ -417,9 +468,25 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService { if (failureNum > 0) { failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:"); throw new RuntimeException(failureMsg.toString()); - } else { + } + + // 第二轮:批量处理 + try { + // 批量插入新记录 + if (!insertList.isEmpty()) { + enterpriseBaseInfoMapper.insertBatch(insertList); + } + + // 批量更新已存在的记录 + if (!updateList.isEmpty()) { + // 批量更新(socialCreditCode已在实体中) + enterpriseBaseInfoMapper.updateBatch(updateList); + } + successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条"); return successMsg.toString(); + } catch (Exception e) { + throw new RuntimeException("批量操作失败:" + e.getMessage()); } } } diff --git a/ruoyi-ccdi/src/main/resources/mapper/ccdi/CcdiBizIntermediaryMapper.xml b/ruoyi-ccdi/src/main/resources/mapper/ccdi/CcdiBizIntermediaryMapper.xml new file mode 100644 index 0000000..0225943 --- /dev/null +++ b/ruoyi-ccdi/src/main/resources/mapper/ccdi/CcdiBizIntermediaryMapper.xml @@ -0,0 +1,55 @@ + + + + + + + INSERT INTO ccdi_biz_intermediary ( + biz_id, person_type, person_sub_type, relation_type, + name, gender, id_type, person_id, mobile, wechat_no, + contact_address, company, social_credit_code, position, + related_num_id, data_source, remark, + created_by, updated_by, create_time, update_time + ) VALUES + + ( + #{item.bizId}, #{item.personType}, #{item.personSubType}, #{item.relationType}, + #{item.name}, #{item.gender}, #{item.idType}, #{item.personId}, #{item.mobile}, #{item.wechatNo}, + #{item.contactAddress}, #{item.company}, #{item.socialCreditCode}, #{item.position}, + #{item.relatedNumId}, #{item.dataSource}, #{item.remark}, + #{item.createdBy}, #{item.updatedBy}, #{item.createTime}, #{item.updateTime} + ) + + + + + + + UPDATE ccdi_biz_intermediary + + person_type = #{item.personType}, + person_sub_type = #{item.personSubType}, + relation_type = #{item.relationType}, + name = #{item.name}, + gender = #{item.gender}, + id_type = #{item.idType}, + person_id = #{item.personId}, + mobile = #{item.mobile}, + wechat_no = #{item.wechatNo}, + contact_address = #{item.contactAddress}, + company = #{item.company}, + social_credit_code = #{item.socialCreditCode}, + position = #{item.position}, + related_num_id = #{item.relatedNumId}, + data_source = #{item.dataSource}, + remark = #{item.remark}, + updated_by = #{item.updatedBy}, + update_time = #{item.updateTime} + + WHERE biz_id = #{item.bizId} + + + + diff --git a/ruoyi-ccdi/src/main/resources/mapper/ccdi/CcdiEnterpriseBaseInfoMapper.xml b/ruoyi-ccdi/src/main/resources/mapper/ccdi/CcdiEnterpriseBaseInfoMapper.xml new file mode 100644 index 0000000..23e8c87 --- /dev/null +++ b/ruoyi-ccdi/src/main/resources/mapper/ccdi/CcdiEnterpriseBaseInfoMapper.xml @@ -0,0 +1,60 @@ + + + + + + + INSERT INTO ccdi_enterprise_base_info ( + social_credit_code, enterprise_name, enterprise_type, enterprise_nature, + industry_class, industry_name, establish_date, register_address, + legal_representative, legal_cert_type, legal_cert_no, + shareholder1, shareholder2, shareholder3, shareholder4, shareholder5, + status, risk_level, ent_source, data_source, + created_by, updated_by, create_time, update_time + ) VALUES + + ( + #{item.socialCreditCode}, #{item.enterpriseName}, #{item.enterpriseType}, #{item.enterpriseNature}, + #{item.industryClass}, #{item.industryName}, #{item.establishDate}, #{item.registerAddress}, + #{item.legalRepresentative}, #{item.legalCertType}, #{item.legalCertNo}, + #{item.shareholder1}, #{item.shareholder2}, #{item.shareholder3}, #{item.shareholder4}, #{item.shareholder5}, + #{item.status}, #{item.riskLevel}, #{item.entSource}, #{item.dataSource}, + #{item.createdBy}, #{item.updatedBy}, #{item.createTime}, #{item.updateTime} + ) + + + + + + + UPDATE ccdi_enterprise_base_info + + enterprise_name = #{item.enterpriseName}, + enterprise_type = #{item.enterpriseType}, + enterprise_nature = #{item.enterpriseNature}, + industry_class = #{item.industryClass}, + industry_name = #{item.industryName}, + establish_date = #{item.establishDate}, + register_address = #{item.registerAddress}, + legal_representative = #{item.legalRepresentative}, + legal_cert_type = #{item.legalCertType}, + legal_cert_no = #{item.legalCertNo}, + shareholder1 = #{item.shareholder1}, + shareholder2 = #{item.shareholder2}, + shareholder3 = #{item.shareholder3}, + shareholder4 = #{item.shareholder4}, + shareholder5 = #{item.shareholder5}, + status = #{item.status}, + risk_level = #{item.riskLevel}, + ent_source = #{item.entSource}, + data_source = #{item.dataSource}, + updated_by = #{item.updatedBy}, + update_time = #{item.updateTime} + + WHERE social_credit_code = #{item.socialCreditCode} + + + +