当前位置: 首页 > news >正文

SQL子查询与MyBatis映射

文章目录

  • 前言
  • 1. 数据库表结构
  • 2. MyBatis Mapper XML
  • 3. Java 实体类
  • 4. 技术点解析
  • 5. 执行效果
  • 6. 优化建议


前言

提示:这里可以添加本文要记录的大概内容:

以下是一个结合 SQL 别名、子查询、MyBatis 字段映射和代码复用的完整案例,以用户管理系统为例:

场景描述
查询用户信息时需同时显示:

  1. 基础用户信息
  2. 所属部门名称
  3. 最近3个月的订单数量
  4. 使用代码复用优化重复SQL片段

1. 数据库表结构

用户表(User)
在这里插入图片描述
部门表(Department)
在这里插入图片描述
订单表(Order)
在这里插入图片描述


2. MyBatis Mapper XML

<!-- 结果映射 -->
<resultMap id="userResultMap" type="UserDTO">
  <id property="userId" column="user_id"/>
  <result property="username" column="username"/>
  <result property="departmentName" column="department_name"/>
  <result property="orderCount" column="order_count"/>
  <result property="createTime" column="create_time"/>
</resultMap>

<!-- 定义可复用的基础字段 -->
<sql id="baseUserColumns">
  u.id AS user_id,
  u.username,
  u.create_time
</sql>

<!-- 定义部门关联字段 -->
<sql id="deptColumns">
  d.dept_name AS department_name
</sql>

<!-- 复合查询 -->
<select id="selectUserWithStats" resultMap="userResultMap">
  SELECT 
    <!-- 复用基础字段 -->
    <include refid="baseUserColumns"/>,
    
    <!-- 复用部门字段 -->
    <include refid="deptColumns"/>,
    
    <!-- 使用子查询和别名 -->
    (
      SELECT COUNT(*) 
      FROM order o 
      WHERE o.user_id = u.id
      AND o.order_time >= DATE_SUB(NOW(), INTERVAL 3 MONTH)
    ) AS order_count
    
  FROM user u
  LEFT JOIN department d ON u.dept_id = d.id
  WHERE u.id = #{userId}
</select>

3. Java 实体类

public class UserDTO {
  private Long userId;       // 映射 user_id
  private String username;   // 直接映射
  private String departmentName; // 映射 department_name
  private Integer orderCount;    // 映射 order_count
  private Date createTime;   // 映射 create_time
  
  // getters/setters
}

4. 技术点解析

  1. SQL 别名(Alias)
   u.id AS user_id,
   d.dept_name AS department_name
  • 解决字段名冲突
  • 实现数据库蛇形命名到Java驼峰命名的转换
  1. 子查询封装
   (SELECT COUNT(*) ...) AS order_count
  • 将复杂统计逻辑封装在子查询中
  • 避免多次查询数据库
  1. MyBatis字段映射
   <resultMap id="userResultMap" type="UserDTO">
     <id property="userId" column="user_id"/>
     <result property="departmentName" column="department_name"/>
   </resultMap>
  • 实现数据库字段到对象属性的映射
  • 处理命名差异问题
  1. SQL代码复用
   <include refid="baseUserColumns"/>
   <include refid="deptColumns"/> 
  • 统一管理公共字段
  • 修改时只需改动一处

5. 执行效果

当调用selectUserWithStats方法查询用户 ID 时:

获取某个特定用户的基本信息及其最近3个月的订单活动情况

生成的SQL:

SELECT 
  u.id AS user_id,
  u.username,
  u.create_time,
  d.dept_name AS department_name,
  (SELECT COUNT(*) 
   FROM order o 
   WHERE o.user_id = u.id
   AND o.order_time >= DATE_SUB(NOW(), INTERVAL 3 MONTH)) AS order_count
FROM user u
LEFT JOIN department d ON u.dept_id = d.id
WHERE u.id = #{id}

下面是对这段SQL子查询语句每一行的详细解释:

  (SELECT COUNT(*) 
   FROM order o 
   WHERE o.user_id = u.id
   AND o.order_time >= DATE_SUB(NOW(), INTERVAL 3 MONTH)) AS order_count
  • 这用于计算特定用户在过去3个月内生成的订单数量。它从order表(别名为o)中计数所有满足条件的记录:user_id与外部查询中的用户ID相匹配,且order_time在当前时间(NOW())起往前推3个月的时间范围内。结果被命名为order_count

查询结果映射:

UserDTO{
  userId=1001, 
  username="张三", 
  departmentName="技术部", 
  orderCount=5, 
  createTime=2023-01-15
}

6. 优化建议

  1. 性能优化:为order.user_idorder_time字段添加索引
  2. 子查询优化:大数据量时可改为LEFT JOIN查询
  3. 动态SQL:添加<if>条件实现动态字段控制
  4. 分页支持:添加LIMIT语句配合PageHelper插件

这个案例完整展示了复杂查询场景下,如何通过MyBatis的特性实现清晰、可维护的SQL编写。


相关文章:

  • plantuml画甘特图gantt
  • AUTOSAR_CP_EthernetSwitchDriver
  • rpc grpc
  • C语言零基础入门教程:操作系统原理(上)
  • 火山引擎云上实战:一键部署 DeepSeek 大模型(蒸馏版)
  • 【工具】ReConPlot一个可视化和解释基因组重排的R包
  • AutoGen学习笔记系列(十六)Examples - Company Research
  • VSTO(C#)Excel开发7:自定义任务窗格
  • 【原创】在高性能服务器上,使用受限用户运行Nginx,充当反向代理服务器[未完待续]
  • 《又是二叉树?递归与回溯的经典应用》
  • 嵌入式人工智能应用- 第七章 人脸识别
  • 什么是OF
  • java学习总结(四):MyBatis
  • 低成本抗衡DeepSeek-R1!QwQ-32B本地部署教程:消费级硬件可部署
  • 分布式事务中TCC、SAGA 或可靠消息事务应该如何理解?
  • WPS的Excel文档如何利用VB脚本批量替换超链接的内容
  • Linux 》》Ubuntu 18 LTS 之后的版本 修改IP地址 主机名
  • TypeScript 中 interface 与 type的使用注意事项 及区别详细介绍
  • TypeScript深度解析:从类型系统到工程化实践
  • MCP服务协议详细介绍
  • 上海市政府党组赴全面从严治党警示教育基地参观学习,推进作风建设走深走实
  • 携程:今年第一季度营业收入约138亿元,入境旅游预订同比增长超100%
  • 设甜蜜打卡点、还能当婚车,上海定制公交车变身“幸福专列”
  • 俄美元首通话超2小时,普京称愿与乌方共同起草和平备忘录
  • 沧州盐碱地“逆天改命”:无用之地变良田,候鸟翔集水草丰美
  • 缅甸发生5.0级地震