# 中介黑名单联合查询功能重构实现总结

## 一、问题描述

原始的SQL错误：`Unknown column 'relation_type_field' in 'field list'`

**根本原因：**

1. 实体类 `CcdiBizIntermediary` 中定义了不存在的字段 `relationTypeField`
2. 实体类中的 `dataSource` 字段与数据库字段 `date_source` 映射不匹配
3. 原有的列表查询实现通过Java层合并两张表的数据,效率较低且无法利用数据库优化

## 二、解决方案

### 2.1 修复实体类字段映射

**文件：** `ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/domain/CcdiBizIntermediary.java`

**修改内容：**

1. 删除了不存在的 `relationTypeField` 字段（第70行）
2. 为 `dataSource` 字段添加了 `@TableField("date_source")` 注解（第70行）

```java
// 修改前
private String relationTypeField;
private String dataSource;

// 修改后
@TableField("date_source")
private String dataSource;
```

### 2.2 创建联合查询Mapper接口

**新增文件：** `ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/mapper/CcdiIntermediaryMapper.java`

**功能：**

- 定义联合查询方法 `selectIntermediaryList()`
- 定义统计查询方法 `selectIntermediaryCount()`
- 支持按中介类型筛选：`1=个人, 2=实体, null=全部`

### 2.3 创建MyBatis XML Mapper

**新增文件：** `ruoyi-info-collection/src/main/resources/mapper/ccdi/CcdiIntermediaryMapper.xml`

**SQL设计策略：**

1. **单表查询模式**（当指定中介类型时）
    - `intermediaryType=1`：仅查询 `ccdi_biz_intermediary` 表
    - `intermediaryType=2`：仅查询 `ccdi_enterprise_base_info` 表

2. **联合查询模式**（当intermediaryType为null时）
    - 使用 `UNION ALL` 联合两张表
    - 外层包裹 `SELECT * FROM (...) AS combined_result` 用于统一排序和分页
    - 按创建时间倒序排列

3. **动态SQL特性**
    - 使用 MyBatis 动态SQL实现灵活的查询条件组合
    - 支持姓名模糊查询
    - 支持证件号/统一社会信用代码精确查询
    - 支持分页（LIMIT + OFFSET）

**查询条件映射：**

| 查询参数             | 个人中介表字段          | 实体中介表字段                                      |
|------------------|------------------|----------------------------------------------|
| name             | name             | enterprise_name                              |
| certificateNo    | person_id        | social_credit_code                           |
| intermediaryType | person_type='中介' | risk_level='1' AND ent_source='INTERMEDIARY' |

### 2.4 优化Service层实现

**文件：** `ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/service/impl/CcdiIntermediaryServiceImpl.java`

**修改内容：**

1. 注入新的 `CcdiIntermediaryMapper`
2. 重写 `selectIntermediaryPage()` 方法，使用XML联合查询
3. 删除原有的Java层合并数据和手动分页逻辑

**性能优势：**

- 数据库层面实现分页，减少内存占用
- 利用数据库索引优化查询性能
- 减少网络传输数据量

### 2.5 扩展查询DTO

**文件：** `ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiIntermediaryQueryDTO.java`

**新增字段：**

```java
private Integer pageNum;   // 页码
private Integer pageSize;  // 每页大小
```

## 三、技术实现细节

### 3.1 分页实现

**MyBatis Plus的分页机制：**

- MyBatis Plus的分页从1开始（`page.getCurrent()`）
- SQL的OFFSET从0开始
- 需要转换：`pageNum = page.getCurrent() - 1`

**SQL分页语法：**

```sql
LIMIT #{pageSize}
OFFSET #{pageNum} * #{pageSize}
```

### 3.2 UNION ALL vs UNION

- **使用 UNION ALL**：保留所有记录，包括重复记录
- **性能优势**：UNION ALL 不进行去重排序，性能更好
- **业务场景**：个人中介和实体中介不会重复，无需去重

### 3.3 动态SQL设计

使用MyBatis的 `<if>` 标签实现：

```xml
<if test="intermediaryType != null and intermediaryType == '1'">
    <!-- 个人中介查询 -->
</if>
<if test="intermediaryType != null and intermediaryType == '2'">
    <!-- 实体中介查询 -->
</if>
<if test="intermediaryType == null or intermediaryType == ''">
    <!-- 联合查询 -->
</if>
```

## 四、测试脚本

**文件：** `doc/test/scripts/test_union_query.sh`

**测试用例：**

1. Test 1: 查询全部中介（UNION查询）
2. Test 2: 仅查询个人中介（单表查询）
3. Test 3: 仅查询实体中介（单表查询）
4. Test 4: 按姓名模糊查询
5. Test 5: 按证件号精确查询
6. Test 6: 分页功能测试
7. Test 7: 组合查询测试（类型+姓名+分页）

## 五、文件清单

### 修改的文件

1. `ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/domain/CcdiBizIntermediary.java` - 删除冗余字段，修复字段映射
2. `ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/service/impl/CcdiIntermediaryServiceImpl.java` - 重构查询逻辑
3. `ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/domain/dto/CcdiIntermediaryQueryDTO.java` - 添加分页参数

### 新增的文件

1. `ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/mapper/CcdiIntermediaryMapper.java` - 联合查询Mapper接口
2. `ruoyi-info-collection/src/main/resources/mapper/ccdi/CcdiIntermediaryMapper.xml` - MyBatis XML Mapper
3. `doc/test/scripts/test_union_query.sh` - 测试脚本

### 删除的文件

1. `ruoyi-info-collection/src/main/resources/mapper/ccdi/CcdiIntermediaryMapper.xml` - 旧的错误配置

## 六、优势总结

### 6.1 性能提升

- **数据库层面分页**：避免加载全部数据到内存
- **索引优化**：充分利用数据库索引
- **减少网络传输**：只传输需要的数据

### 6.2 代码质量

- **职责分离**：查询逻辑集中在Mapper层
- **代码简洁**：删除复杂的Java层合并逻辑
- **易于维护**：SQL集中管理，便于优化

### 6.3 灵活性

- **动态查询**：支持单表和联合查询灵活切换
- **条件组合**：支持多种查询条件组合
- **易于扩展**：后续新增字段或查询条件只需修改XML

## 七、后续建议

1. **索引优化**：
    - `ccdi_biz_intermediary`: 确保字段有合适索引
    - `ccdi_enterprise_base_info`: 确保 `risk_level` 和 `ent_source` 有索引

2. **性能监控**：
    - 监控慢查询日志
    - 根据实际数据量调整分页大小

3. **功能扩展**：
    - 考虑添加更多排序字段选项
    - 考虑支持批量导出时的流式查询

## 八、执行测试

```bash
# Windows环境
cd doc\test\scripts
bash test_union_query.sh

# Linux/Mac环境
cd doc/test/scripts
chmod +x test_union_query.sh
./test_union_query.sh
```

## 九、回滚方案

如果新实现出现问题，可以通过Git回滚到之前的版本：

```bash
git checkout HEAD~1 -- ruoyi-info-collection/src/main/java/com/ruoyi/ccdi/service/impl/CcdiIntermediaryServiceImpl.java
```

删除新增的Mapper文件即可恢复原状。

---

**实现日期：** 2026-02-05
**实现人：** Claude Code
**版本：** v2.0
