springboot+VUE+部署(13。创建多表查询)

基于现有的告警列表查询接口,在返回 x_alarm 表所有数据的同时,根据 devid 关联 x_devicename 表,补充返回设备名称和设备安装地址这两个字段,并且保留原有的分页和条件查询功能。

实现思路

  1. 数据关联 :通过 devidx_alarmx_devicename 表关联,查询时补充设备名称、地址字段;
  2. DTO 封装:创建一个包含告警信息 + 设备信息的 DTO 类,用于接收关联查询结果;
  3. 修改查询逻辑:替换原有的单表分页查询,改为自定义 SQL 关联查询,保留分页和条件过滤;
  4. 结果封装:将查询结果封装成前端需要的格式(总数 + 分页数据)。

完整实现代码

步骤 1:创建告警扩展 DTO 类(包含设备信息)
复制代码
import lombok.Data;
import java.util.Date;

/**
 * 告警信息扩展DTO(包含设备名称和地址)
 */
@Data
public class AlarmExtDTO {
    // 告警表原有字段
    private Integer uid;
    private String devid;
    private String alarmtype;
    private Date alarmtime;
    private String operation;
    private Date operationtime;
    private String operusername;
    
    // 关联设备表的字段
    private String devname;      // 设备名称
    private String devaddress;   // 设备安装地址
}

步骤 2:修改 Mapper 层(自定义关联分页查询)

复制代码
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

public interface AlarmMapper {

    /**
     * 关联查询告警+设备信息(带分页和条件)
     */
    @Select("SELECT " +
            "a.uid, a.devid, a.alarmtype, a.alarmtime, a.operation, " +
            "a.operationtime, a.operusername, " +
            "b.devname, b.devaddress " +
            "FROM x_alarm a " +
            "LEFT JOIN x_devicename b ON a.devid = b.devid " + // 左连接:保证无设备信息的告警也能查询到
            "${ew.customSqlSegment}") // 用于拼接MyBatis-Plus的条件
    IPage<AlarmExtDTO> selectAlarmWithDevice(Page<AlarmExtDTO> page, 
                                            @Param(Constants.WRAPPER) Wrapper<Alarm> wrapper);
}

步骤 3:修改 Service 层(可选,封装业务逻辑)

复制代码
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

@Service
public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements AlarmService {

    @Override
    public Page<AlarmExtDTO> getAlarmWithDevicePage(Page<AlarmExtDTO> page, 
                                                  String devid, String alarmtype) {
        LambdaQueryWrapper<Alarm> wrapper = new LambdaQueryWrapper<>();
        // 保留原有条件过滤
        wrapper.like(StringUtils.hasLength(devid), Alarm::getDevid, devid);
        wrapper.like(StringUtils.hasLength(alarmtype), Alarm::getAlarmtype, alarmtype);
        // 执行关联分页查询
        return baseMapper.selectAlarmWithDevice(page, wrapper);
    }
}

// 对应的Service接口
public interface AlarmService extends IService<Alarm> {
    Page<AlarmExtDTO> getAlarmWithDevicePage(Page<AlarmExtDTO> page, String devid, String alarmtype);
}

步骤 4:修改 Controller 层(最终接口)

复制代码
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.HashMap;

@RestController
public class AlarmController {

    private final AlarmService alarmService;

    // 构造器注入
    public AlarmController(AlarmService alarmService) {
        this.alarmService = alarmService;
    }

    @GetMapping("/alarm/list")
    public Result<Map<String, Object>> getalarmList(
            @RequestParam(value = "devid", required = false) String devid,
            @RequestParam(value = "alarmtype", required = false) String alarmtype,
            @RequestParam(value = "pageNo") Long pageNo,
            @RequestParam(value = "pageSize") Long pageSize) {

        // 构建分页对象
        Page<AlarmExtDTO> page = new Page<>(pageNo, pageSize);
        // 调用关联查询方法
        Page<AlarmExtDTO> resultPage = alarmService.getAlarmWithDevicePage(page, devid, alarmtype);

        // 封装返回结果(保持原有格式)
        HashMap<String, Object> data = new HashMap<>();
        data.put("total", resultPage.getTotal()); // 总条数
        data.put("rows", resultPage.getRecords()); // 分页数据(包含设备名称/地址)
        return Result.success(data);
    }
}

关键说明

  1. 表关联方式 :使用 LEFT JOIN(左连接)而非内连接,确保即使 x_devicename 中没有对应 devid 的记录,告警数据也能正常返回(设备名称 / 地址为 null);
  2. 条件复用 :通过 ${ew.customSqlSegment} 复用 MyBatis-Plus 的 LambdaQueryWrapper 条件,无需手动拼接 where 语句,保留原有的 devidalarmtype 模糊查询;
  3. DTO 设计 :新增 AlarmExtDTO 专门用于接收关联查询结果,避免修改原有 Alarm 实体类,符合 "单一职责" 原则;
  4. 分页兼容:完全保留原有的分页参数(pageNo/pageSize)和返回格式(total/rows),前端无需修改。

测试示例

假设数据库中有以下数据:

  • x_alarm:devid = "DEV001",alarmtype = "故障告警"
  • x_devicename:devid = "DEV001",devname = "温湿度传感器",devaddress = "一号厂房 3 楼"

调用接口:/alarm/list?devid=DEV001&pageNo=1&pageSize=10

总结

  1. 核心改动是通过 LEFT JOIN 关联两张表,并新增 DTO 接收扩展字段;
  2. 复用 MyBatis-Plus 的条件构造器和分页插件,保留原有查询条件和分页逻辑;
  3. 接口返回格式不变,仅在 rows 数组中新增 devnamedevaddress 字段,前端可直接使用。

创建位置规范(遵循 Java 项目最佳实践)

在 Spring Boot/Spring MVC 项目中,DTO(数据传输对象)类的创建位置有固定的规范,通常遵循以下目录结构:

plaintext

复制代码
src/main/java/
└── com/你的项目包名/       # 根包(比如 com.company.project)
    ├── controller/        # 控制器(已有)
    ├── service/           # 服务层(已有)
    ├── mapper/            # Mapper层(已有)
    ├── entity/            # 数据库实体类(对应x_alarm、x_devicename的实体,已有)
    └── dto/               # 新增:专门存放DTO类的目录
        └── alarm/         # 可选:按业务模块细分(比如告警模块)
            └── AlarmExtDTO.java  # 你的告警扩展DTO类

二、IDEA 中具体创建步骤

步骤 1:定位并创建 dto 目录
  1. 在 IDEA 的「Project」面板中,展开 src/main/java → 展开你的项目根包(比如 com.xxx.project);
  2. 右键点击根包 → 选择 NewPackage
  3. 输入包名 dto(如果想按模块细分,可输入 dto.alarm)→ 回车确认。
步骤 2:创建 AlarmExtDTO 类
  1. 右键点击刚创建的 dto(或 dto.alarm)包 → 选择 NewJava Class
  2. 在弹出的输入框中输入类名 AlarmExtDTO → 回车;
  3. 把之前提供的 DTO 代码复制到这个类文件中,补充对应的包名(IDEA 会自动提示补全)。
相关推荐
星辰徐哥16 小时前
Spring Boot 微服务架构设计与实现
spring boot·后端·微服务
星辰徐哥16 小时前
Spring Boot 数据导入导出与报表生成
spring boot·后端·ui
明夜之约16 小时前
Spring Boot 自动装配源码
java·spring boot·后端
Leaton Lee16 小时前
Spring Boot分层架构详解:从Controller到Service再到Mapper的完整流程
java·spring boot·后端·架构
Micro麦可乐16 小时前
Spring Boot 实战:从零设计一个短链系统(含完整代码与数据库设计)
数据库·spring boot·后端·哈希算法·雪花算法·短链系统
Jinkxs16 小时前
Resilience4j- 与 Spring Boot 快速集成:自动配置与基础注解使用
java·spring boot·后端
毕设源码_郑学姐16 小时前
计算机毕业设计springboot网络相册设计与实现 基于Spring Boot框架的在线相册管理系统开发与应用 Spring Boot驱动的网络影集设计与实践
spring boot·后端·课程设计
辣机小司16 小时前
【踩坑记录:Spring Boot 配置文件读取值不一致?警惕 YAML 的“八进制陷阱”与 SnakeYAML 版本之谜】
java·spring boot·后端·yaml·踩坑记录
一条小锦吕*16 小时前
基于Spring Boot + 数据可视化 + 协同过滤算法的推荐系统设计与实现(源码+论文+部署全讲解)
spring boot·算法·信息可视化
Jinkxs16 小时前
Prometheus - 监控微服务:Spring Boot 应用指标暴露与监控
spring boot·微服务·prometheus