Mybatis使用collection標(biāo)簽進(jìn)行樹形結(jié)構(gòu)數(shù)據(jù)查詢時攜帶外部參數(shù)查詢
1. 背景
最近更新博客的評論功能,想實現(xiàn)這么一個需求:
評論使用樹形結(jié)構(gòu)展示,評論提交后,需要后臺審核后才展示到前臺,但是用戶自己可以顯示自己提交的未審核的評論
2. 實施
最初的實現(xiàn)方法是想使用collection進(jìn)行樹形結(jié)構(gòu)查詢
為了實現(xiàn)樹形查詢,需要兩個resultMap,一個為最外層的查詢結(jié)果,另一個是集合里的查詢結(jié)果,也就是對象中的children對應(yīng)的List,因為是樹形結(jié)構(gòu),所以外層和里層的結(jié)構(gòu)基本一樣,下方代碼為兩個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>
因為父查詢中,需要查出頂層的評論,所以parent_reply_id應(yīng)該為null,同時為了查詢出自己評論的,但是未審核的,就需要下方<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并非是查詢的時候傳入的param.authorId,而是父查詢中的查詢結(jié)果的authorId,完全無法達(dá)到想要的效果
墻內(nèi)墻外搜了半天,最終發(fā)現(xiàn)唯一的解決辦法只有這種,在父查詢的時候,把當(dāng)前傳的authorId參數(shù)作為查詢結(jié)果,放到select xxx from中,然后在collection標(biāo)簽中用column屬性關(guān)聯(lián),可是這樣子resultMap就又要多一個列,實在是影響代碼維護(hù),最終選擇放棄了這個方式
3、解決辦法 把所有的子對象都通過java進(jìn)行拼裝,使用遞歸,手動執(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ù)查詢的文章就介紹到這了,更多相關(guān)Mybatis使用collection查詢時攜帶外部參數(shù)查詢內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何將JSON字符串?dāng)?shù)組轉(zhuǎn)對象集合
這篇文章主要介紹了如何將JSON字符串?dāng)?shù)組轉(zhuǎn)對象集合,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06Spring?Boot實現(xiàn)分布式系統(tǒng)中的服務(wù)發(fā)現(xiàn)和注冊(最新推薦)
在本文中,我們深入探討了Spring?Boot如何實現(xiàn)分布式系統(tǒng)中的服務(wù)發(fā)現(xiàn)和注冊,我們使用Eureka作為服務(wù)注冊中心,Ribbon作為負(fù)載均衡器,Hystrix作為熔斷器,成功地實現(xiàn)了服務(wù)發(fā)現(xiàn)、服務(wù)注冊、負(fù)載均衡和服務(wù)熔斷等功能,需要的朋友參考下吧2023-06-06springboot2.5.2與 flowable6.6.0整合流程引擎應(yīng)用分析
這篇文章主要介紹了springboot2.5.2與 flowable6.6.0整合流程引擎應(yīng)用分析,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-07-07JAVA返回PDF文件流并進(jìn)行下載的實現(xiàn)方法
這篇文章主要給大家介紹了關(guān)于JAVA返回PDF文件流并進(jìn)行下載的實現(xiàn)方法,PDF文件流下載是通過HTTP協(xié)議將服務(wù)器上的PDF文件以流的方式發(fā)送給客戶端,供客戶端保存到本地磁盤或直接在瀏覽器中打開,需要的朋友可以參考下2024-02-02基于Spring框架由ConditionalOnMissingBean注解引發(fā)的問題
這篇文章主要介紹了基于Spring框架由ConditionalOnMissingBean注解引發(fā)的問題,具有很好2023-11-11