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 会自动提示补全)。
相关推荐
摇滚侠2 小时前
JAVA 项目教程《苍穹外卖-12》,微信小程序项目,前后端分离,从开发到部署
java·开发语言·vue.js·node.js
wb043072013 小时前
使用 Java 开发 MCP 服务并发布到 Maven 中央仓库完整指南
java·开发语言·spring boot·ai·maven
nbwenren5 小时前
Springboot中SLF4J详解
java·spring boot·后端
helx826 小时前
SpringBoot中自定义Starter
java·spring boot·后端
rleS IONS6 小时前
SpringBoot获取bean的几种方式
java·spring boot·后端
lifewange6 小时前
Go语言-开源编程语言
开发语言·后端·golang
白毛大侠7 小时前
深入理解 Go:用户态和内核态
开发语言·后端·golang
R***z1017 小时前
Spring Boot 整合 MyBatis 与 PostgreSQL 实战指南
spring boot·postgresql·mybatis
王码码20357 小时前
Go语言中的数据库操作:从sqlx到ORM
后端·golang·go·接口
星辰_mya8 小时前
雪花算法和时区的关系
数据库·后端·面试·架构师