Mybatis使用collection標(biāo)簽進(jìn)行樹形結(jié)構(gòu)數(shù)據(jù)查詢時(shí)攜帶外部參數(shù)查詢
1. 背景
最近更新博客的評論功能,想實(shí)現(xiàn)這么一個(gè)需求:
評論使用樹形結(jié)構(gòu)展示,評論提交后,需要后臺審核后才展示到前臺,但是用戶自己可以顯示自己提交的未審核的評論
2. 實(shí)施
最初的實(shí)現(xiàn)方法是想使用collection進(jìn)行樹形結(jié)構(gòu)查詢
為了實(shí)現(xiàn)樹形查詢,需要兩個(gè)resultMap,一個(gè)為最外層的查詢結(jié)果,另一個(gè)是集合里的查詢結(jié)果,也就是對象中的children對應(yīng)的List,因?yàn)槭菢湫谓Y(jié)構(gòu),所以外層和里層的結(jié)構(gòu)基本一樣,下方代碼為兩個(gè)resultMap代碼(示例):
<resultMap type="com.stonewu.blog.core.entity.custom.ReplyTree" id="replyTree">
<id column="id" property="id"/>
<result column="content" property="content"/>
<result column="article_id" property="articleId"/>
<result column="author_id" property="authorId"/>
<result column="parent_reply_id" property="parentReplyId"/>
<result column="check_reply" property="checkReply"/>
<collection column="id=id,authorId=author_id" property="children" ofType="com.stonewu.blog.core.entity.custom.ReplyTree" javaType="java.util.ArrayList" select="getReplyChildren">
</collection>
</resultMap>
<resultMap type="com.stonewu.blog.core.entity.custom.ReplyTree" id="replyTreeChild">
<id column="id" property="id"/>
<result column="content" property="content"/>
<result column="article_id" property="articleId"/>
<result column="author_id" property="authorId"/>
<result column="parent_reply_id" property="parentReplyId"/>
<result column="check_reply" property="checkReply"/>
<collection column="id=id,authorId=author_id" property="children" ofType="com.stonewu.blog.core.entity.custom.ReplyTree" javaType="java.util.ArrayList" select="getReplyChildren">
</collection>
</resultMap>因?yàn)楦覆樵冎?,需要查出頂層的評論,所以parent_reply_id應(yīng)該為null,同時(shí)為了查詢出自己評論的,但是未審核的,就需要下方<if test="param.authorId != null">的代碼
下方代碼為父查詢代碼(示例):
<select id="findReplyTreeByParam" parameterType="com.stonewu.blog.core.entity.custom.ReplyTree"
resultMap="replyTree">
SELECT
r.*, a.title article_title,
m.nick_name author_name
FROM
reply r
LEFT JOIN article a ON r.article_id = a.id
LEFT JOIN menber m ON m.id = r.author_id
WHERE 1 = 1
<if test="param.id != null">
AND a.id = #{param.id}
</if>
<if test="param.articleId != null">
AND article_id = #{param.articleId}
</if>
<if test="param.topReplyId != null">
AND top_reply_id = #{param.topReplyId}
</if>
AND parent_reply_id is null
<if test="param.checkReply != null">
AND ( check_reply = #{param.checkReply}
<if test="param.authorId != null">
or m.id = #{param.authorId}
</if>
)
</if>
<if test="param.replyType != null">
AND reply_type = #{param.replyType}
</if>
</select>子查詢是通過上面resultMap中的collection標(biāo)簽關(guān)聯(lián)的getReplyChildren查詢,查詢語句最初寫的如下
<select id="getReplyChildren" resultMap="replyTreeChild">
SELECT
r.*, a.title article_title,
m.nick_name author_name
FROM
reply r
LEFT JOIN article a ON r.article_id = a.id
LEFT JOIN menber m ON m.id = r.author_id
WHERE 1 = 1
AND parent_reply_id = #{id}
AND (
check_reply = 1
<if test="authorId != null">
or m.id = #{authorId}
</if>
)
</select>最下方的if,里面的authorId并非是查詢的時(shí)候傳入的param.authorId,而是父查詢中的查詢結(jié)果的authorId,完全無法達(dá)到想要的效果
墻內(nèi)墻外搜了半天,最終發(fā)現(xiàn)唯一的解決辦法只有這種,在父查詢的時(shí)候,把當(dāng)前傳的authorId參數(shù)作為查詢結(jié)果,放到select xxx from中,然后在collection標(biāo)簽中用column屬性關(guān)聯(lián),可是這樣子resultMap就又要多一個(gè)列,實(shí)在是影響代碼維護(hù),最終選擇放棄了這個(gè)方式
3、解決辦法 把所有的子對象都通過java進(jìn)行拼裝,使用遞歸,手動(dòng)執(zhí)行多次查詢,每次查詢即可攜帶自己想要的參數(shù)進(jìn)行查詢,代碼示例如下:
/**
* 父查詢
* @param page
* @param param
* @return
*/
@Override
@Cacheable(cacheResolver = BlogCacheConfig.CACHE_RESOLVER_NAME, key = "'findReplyTreeByParam_'+#param.articleId+'_'+#param.checkReply+'_'+#param.authorId+'_page_'+#page.current+'_'+#page.size")
public Page<ReplyTree> findReplyTreeByParam(Page<ReplyTree> page, ReplyTree param) {
Page<ReplyTree> result = mapper.findReplyResultByParam(page, param);
getChildReply(new Page<>(1, 9999), param, result.getRecords());
return result;
}
/**
* 子查詢
* @param page
* @param param
* @param result
*/
private void getChildReply(Page<ReplyTree> page, ReplyTree param, List<ReplyTree> result) {
result.forEach(replyTree -> {
Integer id = replyTree.getId();
param.setParentReplyId(id);
Page<ReplyTree> childReply = mapper.findReplyResultByParam(page, param);
replyTree.setChildren(childReply.getRecords());
getChildReply(page, param, childReply.getRecords());
});
}里面的findReplyResultByParam方法就跟普通的mybatis查詢一致,只需要傳入上級評論ID以及authorId即可,主要的邏輯就是在中間的遞歸,需要把每次查詢的結(jié)果放入上級評論的children中,搞定!
到此這篇關(guān)于Mybatis使用collection標(biāo)簽進(jìn)行樹形結(jié)構(gòu)數(shù)據(jù)查詢時(shí)攜帶外部參數(shù)查詢的文章就介紹到這了,更多相關(guān)Mybatis使用collection查詢時(shí)攜帶外部參數(shù)查詢內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何將JSON字符串?dāng)?shù)組轉(zhuǎn)對象集合
這篇文章主要介紹了如何將JSON字符串?dāng)?shù)組轉(zhuǎn)對象集合,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
Spring?Boot實(shí)現(xiàn)分布式系統(tǒng)中的服務(wù)發(fā)現(xiàn)和注冊(最新推薦)
在本文中,我們深入探討了Spring?Boot如何實(shí)現(xiàn)分布式系統(tǒng)中的服務(wù)發(fā)現(xiàn)和注冊,我們使用Eureka作為服務(wù)注冊中心,Ribbon作為負(fù)載均衡器,Hystrix作為熔斷器,成功地實(shí)現(xiàn)了服務(wù)發(fā)現(xiàn)、服務(wù)注冊、負(fù)載均衡和服務(wù)熔斷等功能,需要的朋友參考下吧2023-06-06
java 數(shù)據(jù)的加密與解密普遍實(shí)例代碼
本篇文章介紹了一個(gè)關(guān)于密鑰查詢的jsp文件簡單實(shí)例代碼,需要的朋友可以參考下2017-04-04
springboot2.5.2與 flowable6.6.0整合流程引擎應(yīng)用分析
這篇文章主要介紹了springboot2.5.2與 flowable6.6.0整合流程引擎應(yīng)用分析,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-07-07
JAVA返回PDF文件流并進(jìn)行下載的實(shí)現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于JAVA返回PDF文件流并進(jìn)行下載的實(shí)現(xiàn)方法,PDF文件流下載是通過HTTP協(xié)議將服務(wù)器上的PDF文件以流的方式發(fā)送給客戶端,供客戶端保存到本地磁盤或直接在瀏覽器中打開,需要的朋友可以參考下2024-02-02
基于Spring框架由ConditionalOnMissingBean注解引發(fā)的問題
這篇文章主要介紹了基于Spring框架由ConditionalOnMissingBean注解引發(fā)的問題,具有很好2023-11-11

