feat(mapper): 添加公司关联查询和关键词搜索功能
- 在多个Mapper XML文件中添加LEFT JOIN credit_company表关联 - 扩展关键词搜索范围,支持通过公司名称进行搜索匹配 - 更新CreditNearbyCompany相关功能,支持按公司ID筛选和导入 - 修改CreditNearbyCompanyParam中companyId字段类型为String - 暂时注释掉纳税人识别号相关的搜索条件 - 统一各信用数据映射文件中的关键词搜索逻辑
This commit is contained in:
@@ -161,6 +161,12 @@ public class CreditNearbyCompanyController extends BaseController {
|
|||||||
Map<String, String> urlByCode = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "统一社会信用代码");
|
Map<String, String> urlByCode = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "统一社会信用代码");
|
||||||
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "企业名称");
|
Map<String, String> urlByName = ExcelImportSupport.readHyperlinksByHeaderKey(file, usedSheetIndex, usedTitleRows, usedHeadRows, "企业名称");
|
||||||
|
|
||||||
|
// 避免逐行写库:按批处理,显著降低 SQL 次数与事务开销
|
||||||
|
final int chunkSize = 500;
|
||||||
|
final int mpBatchSize = 500;
|
||||||
|
List<CreditNearbyCompany> chunkItems = new ArrayList<>(chunkSize);
|
||||||
|
List<Integer> chunkRowNumbers = new ArrayList<>(chunkSize);
|
||||||
|
|
||||||
for (int i = 0; i < list.size(); i++) {
|
for (int i = 0; i < list.size(); i++) {
|
||||||
CreditNearbyCompanyImportParam param = list.get(i);
|
CreditNearbyCompanyImportParam param = list.get(i);
|
||||||
try {
|
try {
|
||||||
@@ -207,14 +213,64 @@ public class CreditNearbyCompanyController extends BaseController {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chunkItems.add(item);
|
||||||
|
chunkRowNumbers.add(excelRowNumber);
|
||||||
|
if (chunkItems.size() >= chunkSize) {
|
||||||
|
successCount += persistImportChunk(chunkItems, chunkRowNumbers, companyId, parentId, type, currentTenantId, mpBatchSize, errorMessages);
|
||||||
|
chunkItems.clear();
|
||||||
|
chunkRowNumbers.clear();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
||||||
|
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!chunkItems.isEmpty()) {
|
||||||
|
successCount += persistImportChunk(chunkItems, chunkRowNumbers, companyId, parentId, type, currentTenantId, mpBatchSize, errorMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errorMessages.isEmpty()) {
|
||||||
|
return success("成功导入" + successCount + "条数据", null);
|
||||||
|
} else {
|
||||||
|
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return fail("导入失败:" + e.getMessage(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int persistImportChunk(List<CreditNearbyCompany> items,
|
||||||
|
List<Integer> excelRowNumbers,
|
||||||
|
Integer companyId,
|
||||||
|
Integer parentId,
|
||||||
|
Integer type,
|
||||||
|
Integer tenantId,
|
||||||
|
int mpBatchSize,
|
||||||
|
List<String> errorMessages) {
|
||||||
|
if (CollectionUtils.isEmpty(items)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return creditNearbyCompanyService.importUpsertChunk(items, companyId, parentId, type, tenantId, mpBatchSize);
|
||||||
|
} catch (Exception batchException) {
|
||||||
|
// 批量失败时降级为逐行处理,尽量输出可定位的错误信息
|
||||||
|
int successCount = 0;
|
||||||
|
for (int i = 0; i < items.size(); i++) {
|
||||||
|
CreditNearbyCompany item = items.get(i);
|
||||||
|
int excelRowNumber = (excelRowNumbers != null && i < excelRowNumbers.size()) ? excelRowNumbers.get(i) : -1;
|
||||||
|
try {
|
||||||
boolean saved = creditNearbyCompanyService.save(item);
|
boolean saved = creditNearbyCompanyService.save(item);
|
||||||
if (!saved) {
|
if (!saved) {
|
||||||
CreditNearbyCompany existing = creditNearbyCompanyService.lambdaQuery()
|
CreditNearbyCompany existing = creditNearbyCompanyService.lambdaQuery()
|
||||||
.eq(!ImportHelper.isBlank(item.getCode()), CreditNearbyCompany::getCode, item.getCode())
|
.eq(!ImportHelper.isBlank(item.getCode()), CreditNearbyCompany::getCode, item.getCode())
|
||||||
.eq(ImportHelper.isBlank(item.getCode()), CreditNearbyCompany::getName, item.getName())
|
.eq(ImportHelper.isBlank(item.getCode()), CreditNearbyCompany::getName, item.getName())
|
||||||
.eq(companyId != null, CreditNearbyCompany::getCompanyId, companyId)
|
.eq(item.getCompanyId() != null, CreditNearbyCompany::getCompanyId, item.getCompanyId())
|
||||||
.eq(parentId != null, CreditNearbyCompany::getParentId, parentId)
|
.eq(item.getParentId() != null, CreditNearbyCompany::getParentId, item.getParentId())
|
||||||
.eq(type != null, CreditNearbyCompany::getType, type)
|
.eq(item.getType() != null, CreditNearbyCompany::getType, item.getType())
|
||||||
|
.eq(item.getTenantId() != null, CreditNearbyCompany::getTenantId, item.getTenantId())
|
||||||
.one();
|
.one();
|
||||||
if (existing != null) {
|
if (existing != null) {
|
||||||
item.setId(existing.getId());
|
item.setId(existing.getId());
|
||||||
@@ -227,22 +283,20 @@ public class CreditNearbyCompanyController extends BaseController {
|
|||||||
successCount++;
|
successCount++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
errorMessages.add("第" + excelRowNumber + "行:保存失败");
|
if (excelRowNumber > 0) {
|
||||||
|
errorMessages.add("第" + excelRowNumber + "行:保存失败");
|
||||||
|
} else {
|
||||||
|
errorMessages.add("保存失败");
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
int excelRowNumber = i + 1 + usedTitleRows + usedHeadRows;
|
if (excelRowNumber > 0) {
|
||||||
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
errorMessages.add("第" + excelRowNumber + "行:" + e.getMessage());
|
||||||
e.printStackTrace();
|
} else {
|
||||||
|
errorMessages.add(e.getMessage());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return successCount;
|
||||||
if (errorMessages.isEmpty()) {
|
|
||||||
return success("成功导入" + successCount + "条数据", null);
|
|
||||||
} else {
|
|
||||||
return success("导入完成,成功" + successCount + "条,失败" + errorMessages.size() + "条", errorMessages);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return fail("导入失败:" + e.getMessage(), null);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,4 +39,24 @@ public interface CreditNearbyCompanyService extends IService<CreditNearbyCompany
|
|||||||
*/
|
*/
|
||||||
CreditNearbyCompany getByIdRel(Integer id);
|
CreditNearbyCompany getByIdRel(Integer id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 导入用:按给定维度(companyId/parentId/type/tenantId)批量 upsert,避免逐行写库导致数据库压力过大。
|
||||||
|
* <p>
|
||||||
|
* 规则:优先按 code 匹配;code 为空时按 name 匹配。
|
||||||
|
*
|
||||||
|
* @param items 待写入数据(需保证 name/code 已做基础清洗/默认值填充)
|
||||||
|
* @param companyId 企业ID(可空)
|
||||||
|
* @param parentId 上级ID(可空)
|
||||||
|
* @param type 类型(可空)
|
||||||
|
* @param tenantId 租户ID(可空)
|
||||||
|
* @param batchSize MyBatis-Plus 批处理大小
|
||||||
|
* @return 本次写入成功的条数(插入 + 更新)
|
||||||
|
*/
|
||||||
|
int importUpsertChunk(List<CreditNearbyCompany> items,
|
||||||
|
Integer companyId,
|
||||||
|
Integer parentId,
|
||||||
|
Integer type,
|
||||||
|
Integer tenantId,
|
||||||
|
int batchSize);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.gxwebsoft.credit.service.impl;
|
package com.gxwebsoft.credit.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import com.gxwebsoft.common.core.web.PageParam;
|
import com.gxwebsoft.common.core.web.PageParam;
|
||||||
import com.gxwebsoft.common.core.web.PageResult;
|
import com.gxwebsoft.common.core.web.PageResult;
|
||||||
@@ -8,8 +9,13 @@ import com.gxwebsoft.credit.mapper.CreditNearbyCompanyMapper;
|
|||||||
import com.gxwebsoft.credit.param.CreditNearbyCompanyParam;
|
import com.gxwebsoft.credit.param.CreditNearbyCompanyParam;
|
||||||
import com.gxwebsoft.credit.service.CreditNearbyCompanyService;
|
import com.gxwebsoft.credit.service.CreditNearbyCompanyService;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Propagation;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 附近企业Service实现
|
* 附近企业Service实现
|
||||||
@@ -44,4 +50,116 @@ public class CreditNearbyCompanyServiceImpl extends ServiceImpl<CreditNearbyComp
|
|||||||
return param.getOne(baseMapper.selectListRel(param));
|
return param.getOne(baseMapper.selectListRel(param));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
|
||||||
|
public int importUpsertChunk(List<CreditNearbyCompany> items,
|
||||||
|
Integer companyId,
|
||||||
|
Integer parentId,
|
||||||
|
Integer type,
|
||||||
|
Integer tenantId,
|
||||||
|
int batchSize) {
|
||||||
|
if (items == null || items.isEmpty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<CreditNearbyCompany> updates = new ArrayList<>();
|
||||||
|
List<CreditNearbyCompany> inserts = new ArrayList<>();
|
||||||
|
|
||||||
|
List<String> codes = new ArrayList<>();
|
||||||
|
List<String> names = new ArrayList<>();
|
||||||
|
|
||||||
|
for (CreditNearbyCompany item : items) {
|
||||||
|
if (item == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (item.getCode() != null) {
|
||||||
|
item.setCode(item.getCode().trim());
|
||||||
|
}
|
||||||
|
if (item.getName() != null) {
|
||||||
|
item.setName(item.getName().trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.getCode() != null && !item.getCode().isEmpty()) {
|
||||||
|
codes.add(item.getCode());
|
||||||
|
} else if (item.getName() != null && !item.getName().isEmpty()) {
|
||||||
|
names.add(item.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, CreditNearbyCompany> existingByCode = new HashMap<>();
|
||||||
|
Map<String, CreditNearbyCompany> existingByName = new HashMap<>();
|
||||||
|
|
||||||
|
if (!codes.isEmpty()) {
|
||||||
|
LambdaQueryWrapper<CreditNearbyCompany> wrapper = buildImportKeyWrapper(companyId, parentId, type, tenantId);
|
||||||
|
wrapper.in(CreditNearbyCompany::getCode, codes);
|
||||||
|
wrapper.select(CreditNearbyCompany::getId, CreditNearbyCompany::getCode);
|
||||||
|
List<CreditNearbyCompany> existingList = list(wrapper);
|
||||||
|
for (CreditNearbyCompany existing : existingList) {
|
||||||
|
if (existing.getCode() != null) {
|
||||||
|
existingByCode.putIfAbsent(existing.getCode().trim(), existing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!names.isEmpty()) {
|
||||||
|
LambdaQueryWrapper<CreditNearbyCompany> wrapper = buildImportKeyWrapper(companyId, parentId, type, tenantId);
|
||||||
|
wrapper.in(CreditNearbyCompany::getName, names);
|
||||||
|
wrapper.select(CreditNearbyCompany::getId, CreditNearbyCompany::getName);
|
||||||
|
List<CreditNearbyCompany> existingList = list(wrapper);
|
||||||
|
for (CreditNearbyCompany existing : existingList) {
|
||||||
|
if (existing.getName() != null) {
|
||||||
|
existingByName.putIfAbsent(existing.getName().trim(), existing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CreditNearbyCompany item : items) {
|
||||||
|
if (item == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
CreditNearbyCompany existing = null;
|
||||||
|
if (item.getCode() != null && !item.getCode().isEmpty()) {
|
||||||
|
existing = existingByCode.get(item.getCode());
|
||||||
|
} else if (item.getName() != null && !item.getName().isEmpty()) {
|
||||||
|
existing = existingByName.get(item.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (existing != null) {
|
||||||
|
item.setId(existing.getId());
|
||||||
|
updates.add(item);
|
||||||
|
} else {
|
||||||
|
inserts.add(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!updates.isEmpty()) {
|
||||||
|
// 直接按主键批量更新,避免 saveOrUpdateBatch 产生额外的存在性查询
|
||||||
|
updateBatchById(updates, batchSize);
|
||||||
|
}
|
||||||
|
if (!inserts.isEmpty()) {
|
||||||
|
saveBatch(inserts, batchSize);
|
||||||
|
}
|
||||||
|
return updates.size() + inserts.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private LambdaQueryWrapper<CreditNearbyCompany> buildImportKeyWrapper(Integer companyId,
|
||||||
|
Integer parentId,
|
||||||
|
Integer type,
|
||||||
|
Integer tenantId) {
|
||||||
|
LambdaQueryWrapper<CreditNearbyCompany> wrapper = new LambdaQueryWrapper<>();
|
||||||
|
if (companyId != null) {
|
||||||
|
wrapper.eq(CreditNearbyCompany::getCompanyId, companyId);
|
||||||
|
}
|
||||||
|
if (parentId != null) {
|
||||||
|
wrapper.eq(CreditNearbyCompany::getParentId, parentId);
|
||||||
|
}
|
||||||
|
if (type != null) {
|
||||||
|
wrapper.eq(CreditNearbyCompany::getType, type);
|
||||||
|
}
|
||||||
|
if (tenantId != null) {
|
||||||
|
wrapper.eq(CreditNearbyCompany::getTenantId, tenantId);
|
||||||
|
}
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user