基於tk.mybatis:mapper實現的通用多表查詢,更新操作及上傳jar到maven中心倉庫(一)
一、前言
本人使用mybatis也有些年頭了。對於mybatis的使用也有點個人的心得。個人感覺mybatis在使用起來比hibernate方便且輕量級,這也是我喜歡使用mybatis的原因之一。但是每次在過了一段時間之後就會出現mybatis的xml檔案裡面的sql語句越來越多,看起來也不是十分美觀,也不是很方便。在之前我也試過建立通用的BaseMapper來解決這個問題,BaseMapper固然也能夠解決這樣的一個問題,但是在我看來著絕非是一個非常有效的方法,偶然的情況下,我接觸到了tk.mybatis.mapper這個框架,簡直就像乾柴遇到烈火,我跟它一拍即合。
二、第一版的實現
但是,在使用過一段時間的通用mapper之後,雖然mapper這個框架已經做的很好了,但是我在實際專案中經常需要使用left join功能和按欄位更新功能,這在目前的mapper框架中是不支援的,於是我就想到了自身來實現其功能,於是就有了下面所展示的第一版:
第一版重點類圖:
圖片可能看的不是很清楚,我來說明下:主要查詢功能的封裝是在BaseExample而SelectBaseExample擴充套件了order by,group by和查詢欄位的功能,UpdateBaseExample封裝了更新的欄位及值的功能。left join功能則是在MultipartSelectExample類中進行封裝。所以在這裡我們可以根據我們的需求來建立SelectBaseExample,UpdateBaseExample或者MultipartSelectExample這三個類。大家可能會感到疑惑為什麼MultipartUpdateExample這個類裡面好像一點東西都沒有呢。其實我在設計的時候是感覺應該存在這樣一個類,但是當我寫出來之後我又不知道更新操作會用到什麼更高階的功能,所以就暫時先空著啦,哈哈,看官老爺們可以無視。
介紹完重要的封裝類之後,我們來看看Mapper的層級結構:
這三個類中主要的兩個類是SelectBaseMapper和UpdateBaseMapper這兩個類,分別有通用的查詢和更新的方法,而BaseExampleMapper這個類則是為了集合查詢和更新等功能的一個輔助類。在使用的時候只需要讓業務Mapper繼承BaseExampleMapper即可。
最後我們再來看看xml檔案的實現。
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.test.mapper.BaseExampleMapper"> <select id = "getObjectByField" parameterType="com.example.test.example.select.SelectBaseExample" resultType="map"> select <foreach collection="baseExample.fields" index="index" item="item" separator=","> ${item} </foreach> from ${baseExample.tableName[0]} <if test="baseExample.tableAlias != null "> ${baseExample.tableAlias[0]} </if> <!-- 判斷是不是MultipartSelectExample並且使用了left join功能 --> <if test="baseExample instanceof com.example.test.example.select.multipart.MultipartSelectExample and baseExample.leftJoinFlag"> LEFT JOIN <foreach collection="baseExample.tableAlias" item="key" index="index" separator=""> <if test="index >= 1"> ${baseExample.tableName[1]} ${key} </if> </foreach> ON ${baseExample.leftJoinOn} </if> <if test="baseExample.equalsWhere != null or baseExample.greaterThanWhere != null or baseExample.lessThanWhere != null or baseExample.notEqualsWhere != null"> <where> <if test="baseExample.equalsWhere != null"> <foreach collection="baseExample.equalsWhere.keys" item="key" index="index" separator="AND"> <if test = "baseExample.tableAlias != null"> ${baseExample.tableAlias[0]}. </if> ${key} = #{baseExample.equalsWhere[${key}]} </foreach> <if test="baseExample.greaterThanWhere != null or baseExample.lessThanWhere != null or baseExample.notEqualsWhere != null"> AND </if> </if> <if test="baseExample.greaterThanWhere != null"> <!-- 遍歷map的key --> <foreach collection="baseExample.greaterThanWhere.keys" item="key" index="index" separator="AND"> <!-- 獲取key對應的value --> ${key} > #{baseExample.greaterThanWhere[${key}]} </foreach> <if test="baseExample.lessThanWhere != null or baseExample.notEqualsWhere != null"> AND </if> </if> <if test="baseExample.lessThanWhere != null"> <foreach collection="baseExample.lessThanWhere.keys" item="key" index="index" separator="AND"> ${key} < #{baseExample.lessThanWhere[${key}]} </foreach> <if test="baseExample.notEqualsWhere != null"> AND </if> </if> <if test ="baseExample.notEqualsWhere != null"> <foreach collection="baseExample.notEqualsWhere.keys" item="key" index="index" separator="AND"> ${key} != #{baseExample.notEqualsWhere[${key}]} </foreach> </if> </where> </if> <if test="baseExample.equalsWhere == null and baseExample.greaterThanWhere == null and baseExample.lessThanWhere == null and baseExample.notEqualsWhere == null"> WHERE 1 = 1 </if> <if test="baseExample.inFields != null and baseExample.inFields.size() > 0"> AND <foreach collection="baseExample.inFields" item="field" index="index" separator="AND"> ${field} in <choose> <when test="index == 0"> <foreach collection="baseExample.inValue1" item="value1" index="index1" separator="," open="(" close=")"> #{value1} </foreach> </when> <otherwise> <foreach collection="baseExample.inValue2" item="value2" index="index2" separator="," open="(" close=")"> #{value2} </foreach> </otherwise> </choose> </foreach> </if> <if test=" baseExample.likeFields != null"> <if test="baseExample.inFields != null and baseExample.inFields.size() > 0"> AND </if> <foreach collection="baseExample.likeFields" item="field" index="index" separator="AND"> ${field} LIKE #{baseExample.likeValues[${index}]} </foreach> </if> <!-- 判斷是否含有group by --> <if test="baseExample.groupBy != null"> GROUP BY ${baseExample.groupBy} </if> <!-- 判斷是否含有order by --> <if test="baseExample.orderBy != null"> ORDER BY <foreach collection="baseExample.orderBy.keys" item="key" index="index" separator=","> ${key} <choose> <when test="baseExample.orderBy[key] == 'DESC'"> DESC </when> <otherwise> ASC </otherwise> </choose> </foreach> </if> </select> </mapper>
以上是通用查詢的xml實現,雖然有點多,但是並不複雜,並且其中的部分內容有註釋相信看官們老爺能夠理解。接下來是更新的通用方法。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.test.mapper.BaseExampleMapper">
<update id = "updateObject" parameterType="com.example.test.example.update.UpdateBaseExample" >
UPDATE ${baseExample.tableName[0]} SET
<if test="baseExample.updateFields != null">
<foreach collection="baseExample.updateFields.keys" item="key" index="index" separator=",">
${key} = #{baseExample.updateFields[${key}]}
</foreach>
</if>
<if test="baseExample.equalsWhere != null or baseExample.greaterThanWhere != null or baseExample.lessThanWhere != null or baseExample.notEqualsWhere != null">
<where>
<if test="baseExample.equalsWhere != null">
<foreach collection="baseExample.equalsWhere.keys" item="key" index="index" separator="AND">
<if test = "baseExample.tableAlias != null">
${baseExample.tableAlias[0]}.
</if>
${key} = #{baseExample.equalsWhere[${key}]}
</foreach>
<if test="baseExample.greaterThanWhere != null or baseExample.lessThanWhere != null or baseExample.notEqualsWhere != null">
AND
</if>
</if>
<if test="baseExample.greaterThanWhere != null">
<foreach collection="baseExample.greaterThanWhere.keys" item="key" index="index" separator="AND">
${key} > #{baseExample.greaterThanWhere[${key}]}
</foreach>
<if test="baseExample.lessThanWhere != null or baseExample.notEqualsWhere != null">
AND
</if>
</if>
<if test="baseExample.lessThanWhere != null">
<foreach collection="baseExample.lessThanWhere.keys" item="key" index="index" separator="AND">
${key} < #{baseExample.lessThanWhere[${key}]}
</foreach>
<if test="baseExample.notEqualsWhere != null">
AND
</if>
</if>
<if test ="baseExample.notEqualsWhere != null">
<foreach collection="baseExample.notEqualsWhere.keys" item="key" index="index" separator="AND">
${key} != #{baseExample.notEqualsWhere[${key}]}
</foreach>
</if>
</where>
</if>
<choose>
<when test="baseExample.equalsWhere != null or baseExample.greaterThanWhere != null or baseExample.lessThanWhere != null">
AND
</when>
<otherwise>
WHERE
</otherwise>
</choose>
<if test="baseExample.inFields != null and baseExample.inFields.size() > 0">
<foreach collection="baseExample.inFields" item="field" index="index" separator="AND">
${field} in
<choose>
<when test="index == 0">
<foreach collection="baseExample.inValue1" item="value1" index="index1" separator="," open="(" close=")">
#{value1}
</foreach>
</when>
<otherwise>
<foreach collection="baseExample.inValue2" item="value2" index="index2" separator="," open="(" close=")">
#{value2}
</foreach>
</otherwise>
</choose>
</foreach>
</if>
<if test=" baseExample.likeFields.size() > 0">
<foreach collection="baseExample.likeFields" item="field" index="index" separator="AND">
${field} LIKE #{baseExample.likeValues[${index}]}
</foreach>
</if>
</update>
</mapper>
更新的通用方法和查詢的通用方法比較類似,再次就不做過多解釋了。
好啦,以上就是第一版全部內容,雖然功能非常全面,效能也不算低,但是我個人認為又有xml,內容還比較亂,程式碼的複用性很差,同時代碼的侵入性很強,不符合我的語預期,所以在下一篇中我將會介紹我的2.0版本,跟1.0版本比較,看官老爺們一定會覺得有質的變化。