查询条件组装代码规范说明.md 6.04 KB

查询条件组装代码规范说明

规范概述

为了保持代码的一致性和可维护性,所有查询条件的组装都应该统一放在 getQueryWrapper 方法中,而不是在 Controller 层进行条件组装。

修改内容

1. 接口层修改

文件: SysUserService.java

修改前:

LambdaQueryWrapper<SysUser> getQueryWrapper(SysUser user);

修改后:

LambdaQueryWrapper<SysUser> getQueryWrapper(UserQueryReq queryReq);

2. 实现层修改

文件: SysUserServiceImpl.java

修改前:

@Override
public LambdaQueryWrapper<SysUser> getQueryWrapper(SysUser user) {
    LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();

    // 基础查询条件
    if (StringUtils.isNotEmpty(user.getUsername())) {
        wrapper.like(SysUser::getUsername, user.getUsername());
    }
    // ... 其他条件

    return wrapper;
}

修改后:

@Override
public LambdaQueryWrapper<SysUser> getQueryWrapper(UserQueryReq queryReq) {
    LambdaQueryWrapper<SysUser> wrapper = new LambdaQueryWrapper<>();

    // 基础查询条件
    if (StringUtils.isNotEmpty(queryReq.getUsername())) {
        wrapper.like(SysUser::getUsername, queryReq.getUsername());
    }

    // 时间范围查询条件
    if (queryReq.getStartTime() != null) {
        wrapper.ge(SysUser::getCreateTime, queryReq.getStartTime());
    }
    if (queryReq.getEndTime() != null) {
        wrapper.le(SysUser::getCreateTime, queryReq.getEndTime());
    }

    // 固定条件
    wrapper.eq(SysUser::getDelFlag, "0");
    wrapper.orderByDesc(SysUser::getCreateTime);

    return wrapper;
}

3. Controller 层简化

文件: SysUserController.java

修改前:

public ApiRes<IPage<UserRes>> list(UserQueryReq queryReq) {
    Page<SysUser> page = new Page<>(queryReq.getPageNum(), queryReq.getPageSize());

    // 构建查询条件
    SysUser queryUser = new SysUser();
    BeanUtils.copyProperties(queryReq, queryUser);

    // 获取基础查询条件
    LambdaQueryWrapper<SysUser> wrapper = sysUserService.getQueryWrapper(queryUser);

    // 添加时间范围查询条件
    if (queryReq.getStartTime() != null) {
        wrapper.ge(SysUser::getCreateTime, queryReq.getStartTime());
    }
    if (queryReq.getEndTime() != null) {
        wrapper.le(SysUser::getCreateTime, queryReq.getEndTime());
    }

    IPage<SysUser> userPage = sysUserService.page(page, wrapper);
    // ... 其他逻辑
}

修改后:

public ApiRes<IPage<UserRes>> list(UserQueryReq queryReq) {
    Page<SysUser> page = new Page<>(queryReq.getPageNum(), queryReq.getPageSize());

    // 获取查询条件包装器(包含所有查询条件)
    LambdaQueryWrapper<SysUser> wrapper = sysUserService.getQueryWrapper(queryReq);

    IPage<SysUser> userPage = sysUserService.page(page, wrapper);
    // ... 其他逻辑
}

代码规范优势

1. 职责分离

  • Controller 层: 只负责接收请求和返回响应
  • Service 层: 负责业务逻辑和查询条件组装
  • Mapper 层: 负责数据库操作

2. 代码复用

  • 查询条件组装逻辑集中在 Service 层
  • 其他 Controller 可以复用相同的查询逻辑
  • 避免重复代码

3. 易于维护

  • 查询条件修改只需要在一个地方进行
  • 逻辑清晰,易于理解和调试
  • 便于单元测试

4. 扩展性强

  • 新增查询条件只需要在 getQueryWrapper 方法中添加
  • 不影响 Controller 层的代码
  • 支持复杂的查询条件组合

实现细节

1. 参数类型统一

  • 使用 UserQueryReq 作为查询参数类型
  • 包含所有可能的查询条件
  • 支持分页参数和查询条件

2. 查询条件处理

// 字符串字段:模糊查询
if (StringUtils.isNotEmpty(queryReq.getUsername())) {
    wrapper.like(SysUser::getUsername, queryReq.getUsername());
}

// 数值字段:精确查询
if (queryReq.getStatus() != null) {
    wrapper.eq(SysUser::getStatus, queryReq.getStatus());
}

// 时间字段:范围查询
if (queryReq.getStartTime() != null) {
    wrapper.ge(SysUser::getCreateTime, queryReq.getStartTime());
}

3. 固定条件处理

// 软删除条件
wrapper.eq(SysUser::getDelFlag, "0");

// 排序条件
wrapper.orderByDesc(SysUser::getCreateTime);

最佳实践

1. 查询条件顺序

  1. 基础查询条件(用户名、姓名等)
  2. 状态查询条件
  3. 时间范围查询条件
  4. 固定条件(软删除、排序)

2. 空值处理

  • 使用 StringUtils.isNotEmpty() 处理字符串字段
  • 使用 != null 处理数值和时间字段
  • 避免空字符串和 null 值的查询

3. 性能优化

  • 合理使用索引字段进行查询
  • 避免全表扫描
  • 使用合适的数据类型

扩展指南

1. 添加新的查询条件

// 在 getQueryWrapper 方法中添加
if (StringUtils.isNotEmpty(queryReq.getNewField())) {
    wrapper.like(SysUser::getNewField, queryReq.getNewField());
}

2. 添加新的查询类型

// 支持多值查询
if (queryReq.getStatusList() != null && !queryReq.getStatusList().isEmpty()) {
    wrapper.in(SysUser::getStatus, queryReq.getStatusList());
}

// 支持时间范围查询
if (queryReq.getStartTime() != null && queryReq.getEndTime() != null) {
    wrapper.between(SysUser::getCreateTime, queryReq.getStartTime(), queryReq.getEndTime());
}

3. 添加复杂查询逻辑

// 支持 OR 条件
if (StringUtils.isNotEmpty(queryReq.getKeyword())) {
    wrapper.and(w -> w.like(SysUser::getUsername, queryReq.getKeyword())
                     .or()
                     .like(SysUser::getRealName, queryReq.getKeyword()));
}

注意事项

  1. 参数验证: 在 Service 层添加参数验证逻辑
  2. 异常处理: 合理处理查询异常
  3. 日志记录: 记录重要的查询操作
  4. 性能监控: 监控查询性能,优化慢查询

相关文件

  • SysUserService.java - 服务接口
  • SysUserServiceImpl.java - 服务实现
  • SysUserController.java - 控制器
  • UserQueryReq.java - 查询请求DTO