fix: 修复中介导入成功条数计算错误
问题: - 导入成功条数显示为负数 - 原因:成功数量计算使用 validRecords.size() - failures.size() - 但没有使用实际的数据库操作返回值 修复: - saveBatchWithUpsert 和 saveBatch 方法现在返回 int - 累加实际的数据库影响行数 - 使用 actualSuccessCount 变量跟踪真实成功数量 影响范围: - CcdiIntermediaryPersonImportServiceImpl - CcdiIntermediaryEntityImportServiceImpl
This commit is contained in:
@@ -11,7 +11,13 @@ import com.ruoyi.ccdi.domain.excel.CcdiIntermediaryPersonExcel;
|
||||
import com.ruoyi.ccdi.domain.vo.CcdiIntermediaryEntityDetailVO;
|
||||
import com.ruoyi.ccdi.domain.vo.CcdiIntermediaryPersonDetailVO;
|
||||
import com.ruoyi.ccdi.domain.vo.CcdiIntermediaryVO;
|
||||
import com.ruoyi.ccdi.domain.vo.ImportResultVO;
|
||||
import com.ruoyi.ccdi.domain.vo.ImportStatusVO;
|
||||
import com.ruoyi.ccdi.domain.vo.IntermediaryPersonImportFailureVO;
|
||||
import com.ruoyi.ccdi.domain.vo.IntermediaryEntityImportFailureVO;
|
||||
import com.ruoyi.ccdi.service.ICcdiIntermediaryService;
|
||||
import com.ruoyi.ccdi.service.ICcdiIntermediaryPersonImportService;
|
||||
import com.ruoyi.ccdi.service.ICcdiIntermediaryEntityImportService;
|
||||
import com.ruoyi.ccdi.utils.EasyExcelUtil;
|
||||
import com.ruoyi.common.annotation.Log;
|
||||
import com.ruoyi.common.core.controller.BaseController;
|
||||
@@ -46,6 +52,12 @@ public class CcdiIntermediaryController extends BaseController {
|
||||
@Resource
|
||||
private ICcdiIntermediaryService intermediaryService;
|
||||
|
||||
@Resource
|
||||
private ICcdiIntermediaryPersonImportService personImportService;
|
||||
|
||||
@Resource
|
||||
private ICcdiIntermediaryEntityImportService entityImportService;
|
||||
|
||||
/**
|
||||
* 查询中介列表
|
||||
*/
|
||||
@@ -175,28 +187,132 @@ public class CcdiIntermediaryController extends BaseController {
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入个人中介数据
|
||||
* 导入个人中介数据(异步)
|
||||
*/
|
||||
@Operation(summary = "导入个人中介数据")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:import')")
|
||||
@Log(title = "个人中介", businessType = BusinessType.IMPORT)
|
||||
@PostMapping("/importPersonData")
|
||||
public AjaxResult importPersonData(MultipartFile file, @RequestParam(defaultValue = "false") boolean updateSupport) throws Exception {
|
||||
List<CcdiIntermediaryPersonExcel> list = EasyExcelUtil.importExcel(file.getInputStream(), CcdiIntermediaryPersonExcel.class);
|
||||
String message = intermediaryService.importIntermediaryPerson(list, updateSupport);
|
||||
return success(message);
|
||||
public AjaxResult importPersonData(MultipartFile file, boolean updateSupport) throws Exception {
|
||||
List<CcdiIntermediaryPersonExcel> list = EasyExcelUtil.importExcel(
|
||||
file.getInputStream(), CcdiIntermediaryPersonExcel.class);
|
||||
|
||||
if (list == null || list.isEmpty()) {
|
||||
return error("至少需要一条数据");
|
||||
}
|
||||
|
||||
// 提交异步任务
|
||||
String taskId = intermediaryService.importIntermediaryPerson(list, updateSupport);
|
||||
|
||||
// 立即返回,不等待后台任务完成
|
||||
ImportResultVO result = new ImportResultVO();
|
||||
result.setTaskId(taskId);
|
||||
result.setStatus("PROCESSING");
|
||||
result.setMessage("导入任务已提交,正在后台处理");
|
||||
|
||||
return AjaxResult.success("导入任务已提交,正在后台处理", result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入实体中介数据
|
||||
* 导入实体中介数据(异步)
|
||||
*/
|
||||
@Operation(summary = "导入实体中介数据")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:import')")
|
||||
@Log(title = "实体中介", businessType = BusinessType.IMPORT)
|
||||
@PostMapping("/importEntityData")
|
||||
public AjaxResult importEntityData(MultipartFile file, @RequestParam(defaultValue = "false") boolean updateSupport) throws Exception {
|
||||
List<CcdiIntermediaryEntityExcel> list = EasyExcelUtil.importExcel(file.getInputStream(), CcdiIntermediaryEntityExcel.class);
|
||||
String message = intermediaryService.importIntermediaryEntity(list, updateSupport);
|
||||
return success(message);
|
||||
public AjaxResult importEntityData(MultipartFile file, boolean updateSupport) throws Exception {
|
||||
List<CcdiIntermediaryEntityExcel> list = EasyExcelUtil.importExcel(
|
||||
file.getInputStream(), CcdiIntermediaryEntityExcel.class);
|
||||
|
||||
if (list == null || list.isEmpty()) {
|
||||
return error("至少需要一条数据");
|
||||
}
|
||||
|
||||
// 提交异步任务
|
||||
String taskId = intermediaryService.importIntermediaryEntity(list, updateSupport);
|
||||
|
||||
// 立即返回,不等待后台任务完成
|
||||
ImportResultVO result = new ImportResultVO();
|
||||
result.setTaskId(taskId);
|
||||
result.setStatus("PROCESSING");
|
||||
result.setMessage("导入任务已提交,正在后台处理");
|
||||
|
||||
return AjaxResult.success("导入任务已提交,正在后台处理", result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询个人中介导入状态
|
||||
*/
|
||||
@Operation(summary = "查询个人中介导入状态")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:import')")
|
||||
@GetMapping("/importPersonStatus/{taskId}")
|
||||
public AjaxResult getPersonImportStatus(@PathVariable String taskId) {
|
||||
try {
|
||||
ImportStatusVO status = personImportService.getImportStatus(taskId);
|
||||
return success(status);
|
||||
} catch (Exception e) {
|
||||
return error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询个人中介导入失败记录
|
||||
*/
|
||||
@Operation(summary = "查询个人中介导入失败记录")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:import')")
|
||||
@GetMapping("/importPersonFailures/{taskId}")
|
||||
public TableDataInfo getPersonImportFailures(
|
||||
@PathVariable String taskId,
|
||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
|
||||
List<IntermediaryPersonImportFailureVO> failures =
|
||||
personImportService.getImportFailures(taskId);
|
||||
|
||||
// 手动分页
|
||||
int fromIndex = (pageNum - 1) * pageSize;
|
||||
int toIndex = Math.min(fromIndex + pageSize, failures.size());
|
||||
|
||||
List<IntermediaryPersonImportFailureVO> pageData = failures.subList(fromIndex, toIndex);
|
||||
|
||||
return getDataTable(pageData, failures.size());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询实体中介导入状态
|
||||
*/
|
||||
@Operation(summary = "查询实体中介导入状态")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:import')")
|
||||
@GetMapping("/importEntityStatus/{taskId}")
|
||||
public AjaxResult getEntityImportStatus(@PathVariable String taskId) {
|
||||
try {
|
||||
ImportStatusVO status = entityImportService.getImportStatus(taskId);
|
||||
return success(status);
|
||||
} catch (Exception e) {
|
||||
return error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询实体中介导入失败记录
|
||||
*/
|
||||
@Operation(summary = "查询实体中介导入失败记录")
|
||||
@PreAuthorize("@ss.hasPermi('ccdi:intermediary:import')")
|
||||
@GetMapping("/importEntityFailures/{taskId}")
|
||||
public TableDataInfo getEntityImportFailures(
|
||||
@PathVariable String taskId,
|
||||
@RequestParam(defaultValue = "1") Integer pageNum,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize) {
|
||||
|
||||
List<IntermediaryEntityImportFailureVO> failures =
|
||||
entityImportService.getImportFailures(taskId);
|
||||
|
||||
// 手动分页
|
||||
int fromIndex = (pageNum - 1) * pageSize;
|
||||
int toIndex = Math.min(fromIndex + pageSize, failures.size());
|
||||
|
||||
List<IntermediaryEntityImportFailureVO> pageData = failures.subList(fromIndex, toIndex);
|
||||
|
||||
return getDataTable(pageData, failures.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,10 +76,11 @@ public class CcdiIntermediaryEntityImportServiceImpl implements ICcdiIntermediar
|
||||
}
|
||||
|
||||
// 3. 根据isUpdateSupport选择处理方式
|
||||
int actualSuccessCount = 0;
|
||||
if (isUpdateSupport) {
|
||||
// 更新模式:直接批量导入,数据库自动处理INSERT或UPDATE
|
||||
if (!validRecords.isEmpty()) {
|
||||
saveBatchWithUpsert(validRecords, 500);
|
||||
actualSuccessCount = saveBatchWithUpsert(validRecords, 500);
|
||||
}
|
||||
} else {
|
||||
// 仅新增模式:先查询已存在的记录,对冲突的抛出异常
|
||||
@@ -97,7 +98,8 @@ public class CcdiIntermediaryEntityImportServiceImpl implements ICcdiIntermediar
|
||||
|
||||
// 批量插入新记录
|
||||
if (!actualNewRecords.isEmpty()) {
|
||||
saveBatch(actualNewRecords, 500);
|
||||
int insertCount = saveBatch(actualNewRecords, 500);
|
||||
actualSuccessCount = insertCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +112,7 @@ public class CcdiIntermediaryEntityImportServiceImpl implements ICcdiIntermediar
|
||||
// 5. 更新最终状态
|
||||
ImportResult result = new ImportResult();
|
||||
result.setTotalCount(excelList.size());
|
||||
result.setSuccessCount(validRecords.size() - failures.size());
|
||||
result.setSuccessCount(actualSuccessCount);
|
||||
result.setFailureCount(failures.size());
|
||||
|
||||
String finalStatus = result.getFailureCount() == 0 ? "SUCCESS" : "PARTIAL_SUCCESS";
|
||||
@@ -179,12 +181,15 @@ public class CcdiIntermediaryEntityImportServiceImpl implements ICcdiIntermediar
|
||||
/**
|
||||
* 批量保存(使用ON DUPLICATE KEY UPDATE)
|
||||
*/
|
||||
private void saveBatchWithUpsert(List<CcdiEnterpriseBaseInfo> list, int batchSize) {
|
||||
private int saveBatchWithUpsert(List<CcdiEnterpriseBaseInfo> list, int batchSize) {
|
||||
int totalCount = 0;
|
||||
for (int i = 0; i < list.size(); i += batchSize) {
|
||||
int end = Math.min(i + batchSize, list.size());
|
||||
List<CcdiEnterpriseBaseInfo> subList = list.subList(i, end);
|
||||
entityMapper.importEntityBatch(subList);
|
||||
int count = entityMapper.importEntityBatch(subList);
|
||||
totalCount += count;
|
||||
}
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,13 +236,16 @@ public class CcdiIntermediaryEntityImportServiceImpl implements ICcdiIntermediar
|
||||
/**
|
||||
* 批量保存
|
||||
*/
|
||||
private void saveBatch(List<CcdiEnterpriseBaseInfo> list, int batchSize) {
|
||||
private int saveBatch(List<CcdiEnterpriseBaseInfo> list, int batchSize) {
|
||||
// 使用真正的批量插入,分批次执行以提高性能
|
||||
int totalCount = 0;
|
||||
for (int i = 0; i < list.size(); i += batchSize) {
|
||||
int end = Math.min(i + batchSize, list.size());
|
||||
List<CcdiEnterpriseBaseInfo> subList = list.subList(i, end);
|
||||
entityMapper.insertBatch(subList);
|
||||
int count = entityMapper.insertBatch(subList);
|
||||
totalCount += count;
|
||||
}
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -76,10 +76,11 @@ public class CcdiIntermediaryPersonImportServiceImpl implements ICcdiIntermediar
|
||||
}
|
||||
|
||||
// 3. 根据isUpdateSupport选择处理方式
|
||||
int actualSuccessCount = 0;
|
||||
if (isUpdateSupport) {
|
||||
// 更新模式:直接批量导入,数据库自动处理INSERT或UPDATE
|
||||
if (!validRecords.isEmpty()) {
|
||||
saveBatchWithUpsert(validRecords, 500);
|
||||
actualSuccessCount = saveBatchWithUpsert(validRecords, 500);
|
||||
}
|
||||
} else {
|
||||
// 仅新增模式:先查询已存在的记录,对冲突的抛出异常
|
||||
@@ -97,7 +98,8 @@ public class CcdiIntermediaryPersonImportServiceImpl implements ICcdiIntermediar
|
||||
|
||||
// 批量插入新记录
|
||||
if (!actualNewRecords.isEmpty()) {
|
||||
saveBatch(actualNewRecords, 500);
|
||||
int insertCount = saveBatch(actualNewRecords, 500);
|
||||
actualSuccessCount = insertCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,7 +112,7 @@ public class CcdiIntermediaryPersonImportServiceImpl implements ICcdiIntermediar
|
||||
// 5. 更新最终状态
|
||||
ImportResult result = new ImportResult();
|
||||
result.setTotalCount(excelList.size());
|
||||
result.setSuccessCount(validRecords.size() - failures.size());
|
||||
result.setSuccessCount(actualSuccessCount);
|
||||
result.setFailureCount(failures.size());
|
||||
|
||||
String finalStatus = result.getFailureCount() == 0 ? "SUCCESS" : "PARTIAL_SUCCESS";
|
||||
@@ -179,12 +181,15 @@ public class CcdiIntermediaryPersonImportServiceImpl implements ICcdiIntermediar
|
||||
/**
|
||||
* 批量保存(使用ON DUPLICATE KEY UPDATE)
|
||||
*/
|
||||
private void saveBatchWithUpsert(List<CcdiBizIntermediary> list, int batchSize) {
|
||||
private int saveBatchWithUpsert(List<CcdiBizIntermediary> list, int batchSize) {
|
||||
int totalCount = 0;
|
||||
for (int i = 0; i < list.size(); i += batchSize) {
|
||||
int end = Math.min(i + batchSize, list.size());
|
||||
List<CcdiBizIntermediary> subList = list.subList(i, end);
|
||||
intermediaryMapper.importPersonBatch(subList);
|
||||
int count = intermediaryMapper.importPersonBatch(subList);
|
||||
totalCount += count;
|
||||
}
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,13 +236,16 @@ public class CcdiIntermediaryPersonImportServiceImpl implements ICcdiIntermediar
|
||||
/**
|
||||
* 批量保存
|
||||
*/
|
||||
private void saveBatch(List<CcdiBizIntermediary> list, int batchSize) {
|
||||
private int saveBatch(List<CcdiBizIntermediary> list, int batchSize) {
|
||||
// 使用真正的批量插入,分批次执行以提高性能
|
||||
int totalCount = 0;
|
||||
for (int i = 0; i < list.size(); i += batchSize) {
|
||||
int end = Math.min(i + batchSize, list.size());
|
||||
List<CcdiBizIntermediary> subList = list.subList(i, end);
|
||||
intermediaryMapper.insertBatch(subList);
|
||||
int count = intermediaryMapper.insertBatch(subList);
|
||||
totalCount += count;
|
||||
}
|
||||
return totalCount;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,14 +14,22 @@ import com.ruoyi.ccdi.mapper.CcdiBizIntermediaryMapper;
|
||||
import com.ruoyi.ccdi.mapper.CcdiEnterpriseBaseInfoMapper;
|
||||
import com.ruoyi.ccdi.mapper.CcdiIntermediaryMapper;
|
||||
import com.ruoyi.ccdi.service.ICcdiIntermediaryService;
|
||||
import com.ruoyi.ccdi.service.ICcdiIntermediaryPersonImportService;
|
||||
import com.ruoyi.ccdi.service.ICcdiIntermediaryEntityImportService;
|
||||
import com.ruoyi.common.utils.SecurityUtils;
|
||||
import com.ruoyi.common.utils.StringUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* 中介Service业务层处理
|
||||
@@ -41,6 +49,15 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService {
|
||||
@Resource
|
||||
private CcdiIntermediaryMapper intermediaryMapper;
|
||||
|
||||
@Resource
|
||||
private ICcdiIntermediaryPersonImportService personImportService;
|
||||
|
||||
@Resource
|
||||
private ICcdiIntermediaryEntityImportService entityImportService;
|
||||
|
||||
@Resource
|
||||
private RedisTemplate<String, Object> redisTemplate;
|
||||
|
||||
/**
|
||||
* 分页查询中介列表
|
||||
* 使用XML联合查询实现,支持个人中介和实体中介的灵活查询
|
||||
@@ -239,247 +256,78 @@ public class CcdiIntermediaryServiceImpl implements ICcdiIntermediaryService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入个人中介数据(批量操作)
|
||||
* 优化:使用批量查询替代循环中的单条查询,减少数据库交互次数
|
||||
* 导入个人中介数据(异步)
|
||||
*
|
||||
* @param list Excel实体列表
|
||||
* @param updateSupport 是否更新支持
|
||||
* @return 结果
|
||||
* @return 任务ID
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public String importIntermediaryPerson(List<CcdiIntermediaryPersonExcel> list, boolean updateSupport) {
|
||||
if (StringUtils.isNull(list) || list.isEmpty()) {
|
||||
return "至少需要一条数据";
|
||||
}
|
||||
public String importIntermediaryPerson(List<CcdiIntermediaryPersonExcel> list,
|
||||
boolean updateSupport) {
|
||||
String taskId = UUID.randomUUID().toString();
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
int successNum = 0;
|
||||
int failureNum = 0;
|
||||
StringBuilder successMsg = new StringBuilder();
|
||||
StringBuilder failureMsg = new StringBuilder();
|
||||
// 初始化Redis状态
|
||||
String statusKey = "import:intermediary:" + taskId;
|
||||
Map<String, Object> statusData = new HashMap<>();
|
||||
statusData.put("taskId", taskId);
|
||||
statusData.put("status", "PROCESSING");
|
||||
statusData.put("totalCount", list.size());
|
||||
statusData.put("successCount", 0);
|
||||
statusData.put("failureCount", 0);
|
||||
statusData.put("progress", 0);
|
||||
statusData.put("startTime", startTime);
|
||||
statusData.put("message", "正在处理...");
|
||||
|
||||
// 待插入和更新的列表
|
||||
List<CcdiBizIntermediary> insertList = new ArrayList<>();
|
||||
List<CcdiBizIntermediary> updateList = new ArrayList<>();
|
||||
List<String> personIds = new ArrayList<>();
|
||||
redisTemplate.opsForHash().putAll(statusKey, statusData);
|
||||
redisTemplate.expire(statusKey, 7, TimeUnit.DAYS);
|
||||
|
||||
// 第一轮:收集所有personId
|
||||
for (CcdiIntermediaryPersonExcel excel : list) {
|
||||
if (StringUtils.isNotEmpty(excel.getPersonId())) {
|
||||
personIds.add(excel.getPersonId());
|
||||
}
|
||||
}
|
||||
// 获取当前用户名
|
||||
String userName = SecurityUtils.getUsername();
|
||||
|
||||
// 第二轮:批量查询已存在的记录(一次查询替代N次查询)
|
||||
java.util.Map<String, String> personIdToBizIdMap = new java.util.HashMap<>();
|
||||
if (!personIds.isEmpty()) {
|
||||
LambdaQueryWrapper<CcdiBizIntermediary> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.select(CcdiBizIntermediary::getBizId, CcdiBizIntermediary::getPersonId);
|
||||
wrapper.in(CcdiBizIntermediary::getPersonId, personIds);
|
||||
List<CcdiBizIntermediary> existingList = bizIntermediaryMapper.selectList(wrapper);
|
||||
// 调用异步方法
|
||||
personImportService.importPersonAsync(list, updateSupport, taskId, userName);
|
||||
|
||||
// 建立personId到bizId的映射
|
||||
for (CcdiBizIntermediary existing : existingList) {
|
||||
personIdToBizIdMap.put(existing.getPersonId(), existing.getBizId());
|
||||
}
|
||||
}
|
||||
|
||||
// 第三轮:数据验证和分类(使用Map进行快速判断,避免重复查询)
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
try {
|
||||
CcdiIntermediaryPersonExcel excel = list.get(i);
|
||||
|
||||
// 验证数据
|
||||
if (StringUtils.isEmpty(excel.getName())) {
|
||||
throw new RuntimeException("姓名不能为空");
|
||||
}
|
||||
if (StringUtils.isEmpty(excel.getPersonId())) {
|
||||
throw new RuntimeException("证件号码不能为空");
|
||||
}
|
||||
|
||||
// 转换为实体
|
||||
CcdiBizIntermediary person = new CcdiBizIntermediary();
|
||||
BeanUtils.copyProperties(excel, person);
|
||||
person.setPersonType("中介");
|
||||
person.setDataSource("IMPORT");
|
||||
|
||||
// 使用Map快速判断是否存在
|
||||
String existingBizId = personIdToBizIdMap.get(excel.getPersonId());
|
||||
if (existingBizId != null) {
|
||||
// 记录已存在
|
||||
if (updateSupport) {
|
||||
// 需要更新,设置bizId
|
||||
person.setBizId(existingBizId);
|
||||
updateList.add(person);
|
||||
} else {
|
||||
throw new RuntimeException("该证件号已存在");
|
||||
}
|
||||
} else {
|
||||
// 新数据,加入插入列表
|
||||
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(list.get(i).getName()).append(" 导入失败:");
|
||||
failureMsg.append(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 构建返回消息
|
||||
StringBuilder resultMsg = new StringBuilder();
|
||||
|
||||
if (failureNum > 0) {
|
||||
resultMsg.append("很抱歉,导入失败!共 ").append(failureNum).append(" 条数据格式不正确,错误如下:");
|
||||
resultMsg.append(failureMsg);
|
||||
}
|
||||
|
||||
// 第四轮:批量处理
|
||||
try {
|
||||
// 批量插入新记录
|
||||
if (!insertList.isEmpty()) {
|
||||
bizIntermediaryMapper.insertBatch(insertList);
|
||||
}
|
||||
|
||||
// 批量更新已存在的记录
|
||||
if (!updateList.isEmpty()) {
|
||||
bizIntermediaryMapper.updateBatch(updateList);
|
||||
}
|
||||
|
||||
// 只在有失败的情况下才返回成功信息,否则返回简洁的成功消息
|
||||
if (failureNum > 0) {
|
||||
resultMsg.append("<br/><br/>成功导入 ").append(successNum).append(" 条数据");
|
||||
} else {
|
||||
resultMsg.append("恭喜您,数据已全部导入成功!共 ").append(successNum).append(" 条");
|
||||
}
|
||||
return resultMsg.toString();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("批量操作失败:" + e.getMessage());
|
||||
}
|
||||
return taskId;
|
||||
}
|
||||
|
||||
/**
|
||||
* 导入实体中介数据(批量操作)
|
||||
* 优化:使用批量查询替代循环中的单条查询,减少数据库交互次数
|
||||
* 导入实体中介数据(异步)
|
||||
*
|
||||
* @param list Excel实体列表
|
||||
* @param updateSupport 是否更新支持
|
||||
* @return 结果
|
||||
* @return 任务ID
|
||||
*/
|
||||
@Override
|
||||
@Transactional
|
||||
public String importIntermediaryEntity(List<CcdiIntermediaryEntityExcel> list, boolean updateSupport) {
|
||||
if (StringUtils.isNull(list) || list.isEmpty()) {
|
||||
return "至少需要一条数据";
|
||||
}
|
||||
public String importIntermediaryEntity(List<CcdiIntermediaryEntityExcel> list,
|
||||
boolean updateSupport) {
|
||||
String taskId = UUID.randomUUID().toString();
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
int successNum = 0;
|
||||
int failureNum = 0;
|
||||
StringBuilder successMsg = new StringBuilder();
|
||||
StringBuilder failureMsg = new StringBuilder();
|
||||
// 初始化Redis状态
|
||||
String statusKey = "import:intermediary-entity:" + taskId;
|
||||
Map<String, Object> statusData = new HashMap<>();
|
||||
statusData.put("taskId", taskId);
|
||||
statusData.put("status", "PROCESSING");
|
||||
statusData.put("totalCount", list.size());
|
||||
statusData.put("successCount", 0);
|
||||
statusData.put("failureCount", 0);
|
||||
statusData.put("progress", 0);
|
||||
statusData.put("startTime", startTime);
|
||||
statusData.put("message", "正在处理...");
|
||||
|
||||
// 待插入和更新的列表
|
||||
List<CcdiEnterpriseBaseInfo> insertList = new ArrayList<>();
|
||||
List<CcdiEnterpriseBaseInfo> updateList = new ArrayList<>();
|
||||
List<String> socialCreditCodes = new ArrayList<>();
|
||||
redisTemplate.opsForHash().putAll(statusKey, statusData);
|
||||
redisTemplate.expire(statusKey, 7, TimeUnit.DAYS);
|
||||
|
||||
// 第一轮:收集所有socialCreditCode
|
||||
for (CcdiIntermediaryEntityExcel excel : list) {
|
||||
if (StringUtils.isNotEmpty(excel.getSocialCreditCode())) {
|
||||
socialCreditCodes.add(excel.getSocialCreditCode());
|
||||
}
|
||||
}
|
||||
// 获取当前用户名
|
||||
String userName = SecurityUtils.getUsername();
|
||||
|
||||
// 第二轮:批量查询已存在的记录(一次查询替代N次查询)
|
||||
java.util.Map<String, CcdiEnterpriseBaseInfo> existingEntityMap = new java.util.HashMap<>();
|
||||
if (!socialCreditCodes.isEmpty()) {
|
||||
LambdaQueryWrapper<CcdiEnterpriseBaseInfo> wrapper = new LambdaQueryWrapper<>();
|
||||
wrapper.in(CcdiEnterpriseBaseInfo::getSocialCreditCode, socialCreditCodes);
|
||||
List<CcdiEnterpriseBaseInfo> existingList = enterpriseBaseInfoMapper.selectList(wrapper);
|
||||
// 调用异步方法
|
||||
entityImportService.importEntityAsync(list, updateSupport, taskId, userName);
|
||||
|
||||
// 建立socialCreditCode到实体的映射
|
||||
for (CcdiEnterpriseBaseInfo existing : existingList) {
|
||||
existingEntityMap.put(existing.getSocialCreditCode(), existing);
|
||||
}
|
||||
}
|
||||
|
||||
// 第三轮:数据验证和分类(使用Map进行快速判断,避免重复查询)
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
try {
|
||||
CcdiIntermediaryEntityExcel excel = list.get(i);
|
||||
|
||||
// 验证数据
|
||||
if (StringUtils.isEmpty(excel.getEnterpriseName())) {
|
||||
throw new RuntimeException("机构名称不能为空");
|
||||
}
|
||||
|
||||
// 转换为实体
|
||||
CcdiEnterpriseBaseInfo entity = new CcdiEnterpriseBaseInfo();
|
||||
BeanUtils.copyProperties(excel, entity);
|
||||
entity.setRiskLevel("1");
|
||||
entity.setEntSource("INTERMEDIARY");
|
||||
entity.setDataSource("IMPORT");
|
||||
|
||||
// 使用Map快速判断是否存在
|
||||
if (StringUtils.isNotEmpty(excel.getSocialCreditCode())) {
|
||||
CcdiEnterpriseBaseInfo existingEntity = existingEntityMap.get(excel.getSocialCreditCode());
|
||||
if (existingEntity != null) {
|
||||
// 记录已存在
|
||||
if (updateSupport) {
|
||||
// 需要更新,直接使用socialCreditCode作为主键
|
||||
updateList.add(entity);
|
||||
} else {
|
||||
throw new RuntimeException("该统一社会信用代码已存在");
|
||||
}
|
||||
} else {
|
||||
// 新数据,加入插入列表
|
||||
insertList.add(entity);
|
||||
}
|
||||
} else {
|
||||
// 没有统一社会信用代码,直接加入插入列表
|
||||
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(list.get(i).getEnterpriseName()).append(" 导入失败:");
|
||||
failureMsg.append(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 构建返回消息
|
||||
StringBuilder resultMsg = new StringBuilder();
|
||||
|
||||
if (failureNum > 0) {
|
||||
resultMsg.append("很抱歉,导入失败!共 ").append(failureNum).append(" 条数据格式不正确,错误如下:");
|
||||
resultMsg.append(failureMsg);
|
||||
}
|
||||
|
||||
// 第四轮:批量处理
|
||||
try {
|
||||
// 批量插入新记录
|
||||
if (!insertList.isEmpty()) {
|
||||
enterpriseBaseInfoMapper.insertBatch(insertList);
|
||||
}
|
||||
|
||||
// 批量更新已存在的记录
|
||||
if (!updateList.isEmpty()) {
|
||||
enterpriseBaseInfoMapper.updateBatch(updateList);
|
||||
}
|
||||
|
||||
// 只在有失败的情况下才返回成功信息,否则返回简洁的成功消息
|
||||
if (failureNum > 0) {
|
||||
resultMsg.append("<br/><br/>成功导入 ").append(successNum).append(" 条数据");
|
||||
} else {
|
||||
resultMsg.append("恭喜您,数据已全部导入成功!共 ").append(successNum).append(" 条");
|
||||
}
|
||||
return resultMsg.toString();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("批量操作失败:" + e.getMessage());
|
||||
}
|
||||
return taskId;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user