Mybatis使用collection標(biāo)簽進(jìn)行樹(shù)形結(jié)構(gòu)數(shù)據(jù)查詢(xún)時(shí)攜帶外部參數(shù)查詢(xún)
1. 背景
最近更新博客的評(píng)論功能,想實(shí)現(xiàn)這么一個(gè)需求:
評(píng)論使用樹(shù)形結(jié)構(gòu)展示,評(píng)論提交后,需要后臺(tái)審核后才展示到前臺(tái),但是用戶(hù)自己可以顯示自己提交的未審核的評(píng)論
2. 實(shí)施
最初的實(shí)現(xiàn)方法是想使用collection進(jìn)行樹(shù)形結(jié)構(gòu)查詢(xún)
為了實(shí)現(xiàn)樹(shù)形查詢(xún),需要兩個(gè)resultMap,一個(gè)為最外層的查詢(xún)結(jié)果,另一個(gè)是集合里的查詢(xún)結(jié)果,也就是對(duì)象中的children對(duì)應(yīng)的List,因?yàn)槭菢?shù)形結(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)楦覆樵?xún)中,需要查出頂層的評(píng)論,所以parent_reply_id應(yīng)該為null,同時(shí)為了查詢(xún)出自己評(píng)論的,但是未審核的,就需要下方<if test="param.authorId != null">的代碼
下方代碼為父查詢(xún)代碼(示例):
<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>子查詢(xún)是通過(guò)上面resultMap中的collection標(biāo)簽關(guān)聯(lián)的getReplyChildren查詢(xún),查詢(xún)語(yǔ)句最初寫(xiě)的如下
<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并非是查詢(xún)的時(shí)候傳入的param.authorId,而是父查詢(xún)中的查詢(xún)結(jié)果的authorId,完全無(wú)法達(dá)到想要的效果
墻內(nèi)墻外搜了半天,最終發(fā)現(xiàn)唯一的解決辦法只有這種,在父查詢(xún)的時(shí)候,把當(dāng)前傳的authorId參數(shù)作為查詢(xún)結(jié)果,放到select xxx from中,然后在collection標(biāo)簽中用column屬性關(guān)聯(lián),可是這樣子resultMap就又要多一個(gè)列,實(shí)在是影響代碼維護(hù),最終選擇放棄了這個(gè)方式
3、解決辦法 把所有的子對(duì)象都通過(guò)java進(jìn)行拼裝,使用遞歸,手動(dòng)執(zhí)行多次查詢(xún),每次查詢(xún)即可攜帶自己想要的參數(shù)進(jìn)行查詢(xún),代碼示例如下:
/**
* 父查詢(xú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;
}
/**
* 子查詢(xún)
* @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查詢(xún)一致,只需要傳入上級(jí)評(píng)論ID以及authorId即可,主要的邏輯就是在中間的遞歸,需要把每次查詢(xún)的結(jié)果放入上級(jí)評(píng)論的children中,搞定!
到此這篇關(guān)于Mybatis使用collection標(biāo)簽進(jìn)行樹(shù)形結(jié)構(gòu)數(shù)據(jù)查詢(xún)時(shí)攜帶外部參數(shù)查詢(xún)的文章就介紹到這了,更多相關(guān)Mybatis使用collection查詢(xún)時(shí)攜帶外部參數(shù)查詢(xún)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java判斷各類(lèi)型字符個(gè)數(shù)實(shí)例代碼
大家好,本篇文章主要講的是java判斷各類(lèi)型字符個(gè)數(shù)實(shí)例代碼,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話(huà)記得收藏一下,方便下次瀏覽2021-12-12
Java?IO流之StringWriter和StringReader用法分析
這篇文章主要介紹了Java?IO流之StringWriter和StringReader用法分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
SpringBoot使用ApplicationEvent&Listener完成業(yè)務(wù)解耦
這篇文章主要介紹了SpringBoot使用ApplicationEvent&Listener完成業(yè)務(wù)解耦示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
使用HttpClient實(shí)現(xiàn)文件的上傳下載方法
下面小編就為大家?guī)?lái)一篇使用HttpClient實(shí)現(xiàn)文件的上傳下載方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-12-12

