java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SQL子查询与MyBatis映射

SQL子查询与MyBatis映射过程

作者:二哈喇子!

本文介绍了使用SQL别名、MyBatis字段映射及代码复用优化SQL片段的完整案例,通过子查询将统计逻辑封装化,减少数据库交互次数,提高性能,字段映射确保数据库字段与Java属性一致,处理命名差异,SQL代码复用统一管理公共字段,只需一处修改

前言

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

场景描述

查询用户信息时需同时显示:

1. 数据库表结构

用户表(User)

1. 数据库表结构

部门表(Department)

1. 数据库表结构_图2

订单表(Order)

1. 数据库表结构_图3

2. MyBatis Mapper XML

<!-- 结果映射 -->
<mapper namespace="com.example.dao.UserMapper">
	<resultMap id="userResultMap" type="实体类的全限定名">
	  <result property="userId" column="USER_ID"/>
	  <result property="username" column="USER_NAME"/>
	  <result property="departmentName" column="DEPARTMENT_NAME"/>
	  <result property="orderCount" column="ORDER_COUNT"/>
	  <result property="createTime" column="CREATE_TIME"/>
	</resultMap>
</mapper>
<!-- 定义可复用的基础字段 -->
<sql id="baseUserColumns">
  u.id AS USER_ID,
  u.username AS USER_NAME,
  u.create_time AS 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;           // 映射 USER_NAME
    private String departmentName;     // 映射 DEPARTMENT_NAME
    private Integer orderCount;        // 映射 ORDER_COUNT
    private Date createTime;           // 映射 CREATE_TIME

    // Getters and Setters
}

4. 技术点解析

子查询封装

(SELECT COUNT(*) ...) AS ORDER_COUNT

MyBatis字段映射

<resultMap id="userResultMap" type="UserDTO">
  <id property="userId" column="USER_ID"/>
  <result property="departmentName" column="DEPARTMENT_NAME"/>
</resultMap>

SQL代码复用

<include refid="baseUserColumns"/>
<include refid="deptColumns"/> 

这样整理后的内容更清晰地反映了每个技术点的作用及其重要性,并提供了关于如何正确实现这些功能的具体指导。

5. 执行效果

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

生成的SQL

在AS后面,不可以直接写字段名,一定要通过数据库字段(column) → 映射到 → Java 对象属性(property)

比如:

生成的SQL

SELECT 
  U.ID AS USER_ID,
  U.USERNAME AS USER_NAME,
  U.CREATE_TIME AS 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(CURRENT_DATE(), INTERVAL 3 MONTH)) AS ORDER_COUNT
FROM USER U
LEFT JOIN DEPARTMENT D ON U.DEPT_ID = D.ID
WHERE U.ID = #{userId}

注意事项:

SQL子查询解释

(SELECT COUNT(*) 
 FROM `order` o 
 WHERE o.user_id = u.id
 AND o.order_time >= DATE_SUB(CURRENT_DATE(), INTERVAL 3 MONTH)) AS ORDER_COUNT

查询结果映射

UserDTO{
  userId=1001, 
  username="张三", 
  departmentName="技术部", 
  orderCount=5, 
  createTime=2023-01-15 // 假设时间为2023年1月15日
}

6. 注意

在MyBatis的<result>标签中,column属性用于指定数据库表中的列名,而property属性则指定了对应的Java对象中的属性名。具体来说:

标签的作用

column属性

property 属性

这个属性指定了Java对象中的属性名。MyBatis会将查询结果集中对应列(通过column指定)的值赋给这个属性

如果在MyBatis Mapper XML中遇到两个一样的column,比如说实体中先来了一个name字段,又来了一个newName字段, column属性都取名叫 NAME ,这不对,要给后来的newName字段取一个新名字

例:NEW_NAME

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

您可能感兴趣的文章:
阅读全文