feat: 导入功能改为批量插入和批量更新
## 修改内容 ### Mapper 接口 - CcdiBizIntermediaryMapper: 新增 insertBatch() 和 updateBatch() 方法 - CcdiEnterpriseBaseInfoMapper: 新增 insertBatch() 和 updateBatch() 方法 ### Mapper XML - 新增 CcdiBizIntermediaryMapper.xml: 实现个人中介的批量插入和更新 - 新增 CcdiEnterpriseBaseInfoMapper.xml: 实现实体中介的批量插入和更新 - 批量插入使用 VALUES (...), (...), (...) 语法 - 批量更新使用 foreach 分隔多条 UPDATE 语句 ### Service 实现 - importIntermediaryPerson(): 改为两轮处理模式 - 第一轮:数据验证和分类(区分插入和更新) - 第二轮:批量插入新记录 + 批量更新已存在记录 - importIntermediaryEntity(): 改为两轮处理模式 - 第一轮:数据验证和分类(区分插入和更新) - 第二轮:批量插入新记录 + 批量更新已存在记录 ## 性能优化 - 从原来的逐条插入/更新改为批量操作 - 减少数据库连接次数,提升大数据量导入性能 - 事务一致性保证,全部成功或全部回滚 编译验证:通过
This commit is contained in:
@@ -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<CcdiBizIntermediary> {
|
||||
|
||||
/**
|
||||
* 批量插入个人中介
|
||||
*
|
||||
* @param list 个人中介列表
|
||||
* @return 插入行数
|
||||
*/
|
||||
int insertBatch(List<CcdiBizIntermediary> list);
|
||||
|
||||
/**
|
||||
* 批量更新个人中介
|
||||
*
|
||||
* @param list 个人中介列表
|
||||
* @return 更新行数
|
||||
*/
|
||||
int updateBatch(List<CcdiBizIntermediary> list);
|
||||
}
|
||||
|
||||
@@ -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<CcdiEnterpriseBaseInfo> {
|
||||
|
||||
/**
|
||||
* 批量插入实体中介
|
||||
*
|
||||
* @param list 实体中介列表
|
||||
* @return 插入行数
|
||||
*/
|
||||
int insertBatch(List<CcdiEnterpriseBaseInfo> list);
|
||||
|
||||
/**
|
||||
* 批量更新实体中介
|
||||
*
|
||||
* @param list 实体中介列表
|
||||
* @return 更新行数
|
||||
*/
|
||||
int updateBatch(List<CcdiEnterpriseBaseInfo> list);
|
||||
}
|
||||
|
||||
@@ -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<CcdiBizIntermediary> insertList = new ArrayList<>();
|
||||
List<CcdiBizIntermediary> updateList = new ArrayList<>();
|
||||
List<String> 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<CcdiBizIntermediary> 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("<br/>").append(successNum).append("、").append(excel.getName()).append(" 导入成功");
|
||||
} catch (Exception e) {
|
||||
failureNum++;
|
||||
failureMsg.append("<br/>").append(failureNum).append("、").append(excel.getName()).append(" 导入失败:");
|
||||
failureMsg.append("<br/>").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<CcdiBizIntermediary> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.in(CcdiBizIntermediary::getPersonId, personIds);
|
||||
List<CcdiBizIntermediary> existingList = bizIntermediaryMapper.selectList(wrapper);
|
||||
|
||||
// 建立personId到bizId的映射
|
||||
java.util.Map<String, String> 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<CcdiEnterpriseBaseInfo> insertList = new ArrayList<>();
|
||||
List<CcdiEnterpriseBaseInfo> updateList = new ArrayList<>();
|
||||
List<String> 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("<br/>").append(successNum).append("、").append(excel.getEnterpriseName()).append(" 导入成功");
|
||||
} catch (Exception e) {
|
||||
failureNum++;
|
||||
failureMsg.append("<br/>").append(failureNum).append("、").append(excel.getEnterpriseName()).append(" 导入失败:");
|
||||
failureMsg.append("<br/>").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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.ccdi.mapper.CcdiBizIntermediaryMapper">
|
||||
|
||||
<!-- 批量插入个人中介 -->
|
||||
<insert id="insertBatch" parameterType="java.util.List">
|
||||
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
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(
|
||||
#{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}
|
||||
)
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<!-- 批量更新个人中介 -->
|
||||
<update id="updateBatch" parameterType="java.util.List">
|
||||
<foreach collection="list" item="item" separator=";">
|
||||
UPDATE ccdi_biz_intermediary
|
||||
<set>
|
||||
<if test="item.personType != null">person_type = #{item.personType},</if>
|
||||
<if test="item.personSubType != null">person_sub_type = #{item.personSubType},</if>
|
||||
<if test="item.relationType != null">relation_type = #{item.relationType},</if>
|
||||
<if test="item.name != null and item.name != ''">name = #{item.name},</if>
|
||||
<if test="item.gender != null">gender = #{item.gender},</if>
|
||||
<if test="item.idType != null">id_type = #{item.idType},</if>
|
||||
<if test="item.personId != null and item.personId != ''">person_id = #{item.personId},</if>
|
||||
<if test="item.mobile != null">mobile = #{item.mobile},</if>
|
||||
<if test="item.wechatNo != null">wechat_no = #{item.wechatNo},</if>
|
||||
<if test="item.contactAddress != null">contact_address = #{item.contactAddress},</if>
|
||||
<if test="item.company != null">company = #{item.company},</if>
|
||||
<if test="item.socialCreditCode != null">social_credit_code = #{item.socialCreditCode},</if>
|
||||
<if test="item.position != null">position = #{item.position},</if>
|
||||
<if test="item.relatedNumId != null">related_num_id = #{item.relatedNumId},</if>
|
||||
<if test="item.dataSource != null">data_source = #{item.dataSource},</if>
|
||||
<if test="item.remark != null">remark = #{item.remark},</if>
|
||||
<if test="item.updatedBy != null">updated_by = #{item.updatedBy},</if>
|
||||
update_time = #{item.updateTime}
|
||||
</set>
|
||||
WHERE biz_id = #{item.bizId}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.ruoyi.ccdi.mapper.CcdiEnterpriseBaseInfoMapper">
|
||||
|
||||
<!-- 批量插入实体中介 -->
|
||||
<insert id="insertBatch" parameterType="java.util.List">
|
||||
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
|
||||
<foreach collection="list" item="item" separator=",">
|
||||
(
|
||||
#{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}
|
||||
)
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<!-- 批量更新实体中介 -->
|
||||
<update id="updateBatch" parameterType="java.util.List">
|
||||
<foreach collection="list" item="item" separator=";">
|
||||
UPDATE ccdi_enterprise_base_info
|
||||
<set>
|
||||
<if test="item.enterpriseName != null and item.enterpriseName != ''">enterprise_name = #{item.enterpriseName},</if>
|
||||
<if test="item.enterpriseType != null">enterprise_type = #{item.enterpriseType},</if>
|
||||
<if test="item.enterpriseNature != null">enterprise_nature = #{item.enterpriseNature},</if>
|
||||
<if test="item.industryClass != null">industry_class = #{item.industryClass},</if>
|
||||
<if test="item.industryName != null">industry_name = #{item.industryName},</if>
|
||||
<if test="item.establishDate != null">establish_date = #{item.establishDate},</if>
|
||||
<if test="item.registerAddress != null">register_address = #{item.registerAddress},</if>
|
||||
<if test="item.legalRepresentative != null">legal_representative = #{item.legalRepresentative},</if>
|
||||
<if test="item.legalCertType != null">legal_cert_type = #{item.legalCertType},</if>
|
||||
<if test="item.legalCertNo != null">legal_cert_no = #{item.legalCertNo},</if>
|
||||
<if test="item.shareholder1 != null">shareholder1 = #{item.shareholder1},</if>
|
||||
<if test="item.shareholder2 != null">shareholder2 = #{item.shareholder2},</if>
|
||||
<if test="item.shareholder3 != null">shareholder3 = #{item.shareholder3},</if>
|
||||
<if test="item.shareholder4 != null">shareholder4 = #{item.shareholder4},</if>
|
||||
<if test="item.shareholder5 != null">shareholder5 = #{item.shareholder5},</if>
|
||||
<if test="item.status != null">status = #{item.status},</if>
|
||||
<if test="item.riskLevel != null">risk_level = #{item.riskLevel},</if>
|
||||
<if test="item.entSource != null">ent_source = #{item.entSource},</if>
|
||||
<if test="item.dataSource != null">data_source = #{item.dataSource},</if>
|
||||
<if test="item.updatedBy != null">updated_by = #{item.updatedBy},</if>
|
||||
update_time = #{item.updateTime}
|
||||
</set>
|
||||
WHERE social_credit_code = #{item.socialCreditCode}
|
||||
</foreach>
|
||||
</update>
|
||||
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user