SQL子查詢與MyBatis映射過(guò)程
前言
以下是一個(gè)結(jié)合 SQL 別名、子查詢、MyBatis 字段映射和代碼復(fù)用的完整案例,以用戶管理系統(tǒng)為例:
場(chǎng)景描述:
查詢用戶信息時(shí)需同時(shí)顯示:
- 基礎(chǔ)用戶信息
- 所屬部門名稱
- 最近3個(gè)月的訂單數(shù)量
- 使用代碼復(fù)用優(yōu)化重復(fù)SQL片段
1. 數(shù)據(jù)庫(kù)表結(jié)構(gòu)
用戶表(User)

部門表(Department)

訂單表(Order)

2. MyBatis Mapper XML
<!-- 結(jié)果映射 -->
<mapper namespace="com.example.dao.UserMapper">
<resultMap id="userResultMap" type="實(shí)體類的全限定名">
<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>
<!-- 定義可復(fù)用的基礎(chǔ)字段 -->
<sql id="baseUserColumns">
u.id AS USER_ID,
u.username AS USER_NAME,
u.create_time AS CREATE_TIME
</sql>
<!-- 定義部門關(guān)聯(lián)字段 -->
<sql id="deptColumns">
d.dept_name AS DEPARTMENT_NAME
</sql>
<!-- 復(fù)合查詢 -->
<select id="selectUserWithStats" resultMap="userResultMap">
SELECT
<!-- 復(fù)用基礎(chǔ)字段 -->
<include refid="baseUserColumns"/>,
<!-- 復(fù)用部門字段 -->
<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 實(shí)體類
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. 技術(shù)點(diǎn)解析
子查詢封裝
(SELECT COUNT(*) ...) AS ORDER_COUNT
- 將復(fù)雜統(tǒng)計(jì)邏輯封裝在子查詢中:這種方法可以使得主查詢更加簡(jiǎn)潔,同時(shí)將復(fù)雜的業(yè)務(wù)邏輯(例如統(tǒng)計(jì)訂單數(shù)量)隔離在一個(gè)子查詢內(nèi),便于維護(hù)。
- 避免多次查詢數(shù)據(jù)庫(kù):通過(guò)一次性獲取所有所需的數(shù)據(jù)(包括通過(guò)子查詢計(jì)算得到的數(shù)據(jù)),減少了與數(shù)據(jù)庫(kù)交互的次數(shù),提高了性能。
MyBatis字段映射
<resultMap id="userResultMap" type="UserDTO"> <id property="userId" column="USER_ID"/> <result property="departmentName" column="DEPARTMENT_NAME"/> </resultMap>
- 實(shí)現(xiàn)數(shù)據(jù)庫(kù)字段到對(duì)象屬性的映射:
resultMap用于定義如何將數(shù)據(jù)庫(kù)查詢結(jié)果映射到Java對(duì)象的屬性上。 - 處理命名差異問(wèn)題:通過(guò)明確指定
column和property,解決了數(shù)據(jù)庫(kù)字段命名與Java屬性命名不一致的問(wèn)題,同時(shí)也考慮了大小寫的差異。
SQL代碼復(fù)用
<include refid="baseUserColumns"/> <include refid="deptColumns"/>
- 統(tǒng)一管理公共字段:使用
<sql>標(biāo)簽定義可復(fù)用的SQL片段,可以在不同的查詢中引用這些片段,增強(qiáng)了代碼的一致性和可維護(hù)性。 - 修改時(shí)只需改動(dòng)一處:如果基礎(chǔ)字段發(fā)生變化,只需要在定義的SQL片段中進(jìn)行一次修改,而不需要在每一個(gè)引用該片段的地方分別更新。
這樣整理后的內(nèi)容更清晰地反映了每個(gè)技術(shù)點(diǎn)的作用及其重要性,并提供了關(guān)于如何正確實(shí)現(xiàn)這些功能的具體指導(dǎo)。
5. 執(zhí)行效果
當(dāng)調(diào)用selectUserWithStats方法查詢用戶ID時(shí):
- 目標(biāo):獲取某個(gè)特定用戶的基本信息及其最近3個(gè)月的訂單活動(dòng)情況。
生成的SQL
在AS后面,不可以直接寫字段名,一定要通過(guò)數(shù)據(jù)庫(kù)字段(column) → 映射到 → Java 對(duì)象屬性(property)
比如:

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}注意事項(xiàng):
- 使用了反引號(hào)(``)包裹
order表名,因?yàn)?code>order是SQL關(guān)鍵字。 - 使用
CURRENT_DATE()函數(shù)代替NOW()來(lái)確保只考慮日期部分(如果時(shí)間部分不重要)。 - 確保別名使用大寫,與之前定義的
resultMap中的column屬性匹配。
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
- 作用:計(jì)算特定用戶在過(guò)去3個(gè)月內(nèi)生成的訂單數(shù)量。
- 邏輯:從
order表(別名為o)中計(jì)數(shù)所有滿足條件的記錄:user_id與外部查詢中的用戶ID相匹配,且order_time在當(dāng)前日期起往前推3個(gè)月的時(shí)間范圍內(nèi)。結(jié)果被命名為ORDER_COUNT。
查詢結(jié)果映射
UserDTO{
userId=1001,
username="張三",
departmentName="技術(shù)部",
orderCount=5,
createTime=2023-01-15 // 假設(shè)時(shí)間為2023年1月15日
}
- 說(shuō)明:此映射顯示了如何將查詢結(jié)果轉(zhuǎn)換為Java對(duì)象。每個(gè)數(shù)據(jù)庫(kù)字段通過(guò)MyBatis的
resultMap配置正確映射到相應(yīng)的Java屬性上,確保數(shù)據(jù)類型和命名的一致性。
6. 注意
在MyBatis的<result>標(biāo)簽中,column屬性用于指定數(shù)據(jù)庫(kù)表中的列名,而property屬性則指定了對(duì)應(yīng)的Java對(duì)象中的屬性名。具體來(lái)說(shuō):
標(biāo)簽的作用
<result>:用于映射簡(jiǎn)單數(shù)據(jù)類型的結(jié)果集列到Java對(duì)象的屬性上。它通常用于非主鍵字段的映射。
column屬性
- 含義:表示數(shù)據(jù)庫(kù)查詢結(jié)果集中列的名稱。這個(gè)名稱必須與SQL查詢返回的列名(包括別名)完全一致。
- 用途:告訴MyBatis從哪個(gè)列中獲取數(shù)據(jù),并將其映射到Java對(duì)象的指定屬性上。
property 屬性
這個(gè)屬性指定了Java對(duì)象中的屬性名。MyBatis會(huì)將查詢結(jié)果集中對(duì)應(yīng)列(通過(guò)column指定)的值賦給這個(gè)屬性
- 數(shù)據(jù)庫(kù)中的表(Table)會(huì)被映射為類(Class)。
- 表中的列(Column)會(huì)被映射為類的屬性(Field/Property)。
- 表中的行(Row)會(huì)被映射為類的實(shí)例(Object)。
如果在MyBatis Mapper XML中遇到兩個(gè)一樣的column,比如說(shuō)實(shí)體中先來(lái)了一個(gè)name字段,又來(lái)了一個(gè)newName字段, column屬性都取名叫 NAME ,這不對(duì),要給后來(lái)的newName字段取一個(gè)新名字
例:NEW_NAME
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java隊(duì)列實(shí)現(xiàn)方法(順序隊(duì)列,鏈?zhǔn)疥?duì)列,循環(huán)隊(duì)列)
下面小編就為大家分享一篇java隊(duì)列實(shí)現(xiàn)方法(順序隊(duì)列,鏈?zhǔn)疥?duì)列,循環(huán)隊(duì)列),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-12-12
Java concurrency集合之 CopyOnWriteArrayList_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了Java concurrency集合之 CopyOnWriteArrayList的相關(guān)資料,需要的朋友可以參考下2017-06-06
Docker環(huán)境下Spring Boot應(yīng)用內(nèi)存飆升分析與解決場(chǎng)景分析
當(dāng)運(yùn)行一個(gè)Spring Boot項(xiàng)目時(shí),如果未設(shè)置JVM內(nèi)存參數(shù),Spring Boot默認(rèn)會(huì)采用JVM自身默認(rèn)的配置策略,接下來(lái)通過(guò)本文給大家介紹Docker環(huán)境下Spring Boot應(yīng)用內(nèi)存飆升分析與解決方法,需要的朋友參考下吧2021-08-08
java中@EnableAutoConfiguration注解使用
在Spring Boot框架中,@EnableAutoConfiguration是一種非常重要的注解,本文就來(lái)介紹一下java中@EnableAutoConfiguration注解使用,感興趣的可以了解一下2023-11-11
JVM入門之JVM內(nèi)存結(jié)構(gòu)內(nèi)容詳解
這篇文章主要介紹了JVM入門之JVM內(nèi)存結(jié)構(gòu)內(nèi)容詳解,本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-09-09
response.sendRedirect()實(shí)現(xiàn)重定向(頁(yè)面跳轉(zhuǎn))
在Java web開(kāi)發(fā)中,使用response.sendRedirect()可實(shí)現(xiàn)重定向功能。本文將介紹如何使用該方法進(jìn)行頁(yè)面跳轉(zhuǎn),以及該方法的使用場(chǎng)景和注意事項(xiàng),感興趣的可以了解一下2023-04-04
Springboot之@ConfigurationProperties注解解讀
在Spring Boot中,@EnableConfigurationProperties注解的主要作用是激活@ConfigurationProperties注解的配置屬性類,從而讓配置屬性類能被Spring容器管理,這樣的話,我們就可以在屬性類中輕松地使用@ConfigurationProperties來(lái)綁定配置文件中的屬性2024-10-10
spring?aop?pointcut?添加多個(gè)execution方式
這篇文章主要介紹了spring?aop?pointcut?添加多個(gè)execution方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11

