Mybatis自關(guān)聯(lián)查詢一對多查詢的實(shí)現(xiàn)示例
注:代碼已托管在GitHub上,地址是:https://github.com/Damaer/Mybatis-Learning ,項(xiàng)目是mybatis-13-oneself-one2many,需要自取,需要配置maven環(huán)境以及mysql環(huán)境(sql語句在resource下的test.sql中),覺得有用可以點(diǎn)個(gè)小星星。
docsify文檔地址在:https://damaer.github.io/Mybatis-Learning/#/
所謂自關(guān)聯(lián)查詢,是指自己既然充當(dāng)一方,又充當(dāng)多方。比如新聞欄目的數(shù)據(jù)表,自己可以是父欄目,也可以是多方,子欄目。在數(shù)據(jù)表里面實(shí)現(xiàn)就是一張表,有一個(gè)外鍵pid,用來表示該欄目的父欄目,一級欄目沒有父欄目的,可以將其外鍵設(shè)置為0。
DB表如下:

查詢指定欄目的所有子孫欄目
查詢指定目錄的所有子孫目錄,我們需要使用遞歸的思想,查出當(dāng)前欄目之后,需要將當(dāng)前欄目的id作為下一級欄目的pid。
實(shí)體類NewsLabel.java,使用一對多的關(guān)系:
import java.util.Set;
public class NewsLabel {
private Integer id;
private String name;
private Set<NewsLabel>children;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<NewsLabel> getChildren() {
return children;
}
public void setChildren(Set<NewsLabel> children) {
this.children = children;
}
@Override
public String toString() {
return "NewsLabel [id=" + id + ", name=" + name + ", children="
+ children + "]";
}
}
定義sql接口:
public interface INewsLabelDao {
List<NewsLabel> selectChildByParentId(int pid);
}
mapper.xml文件,在遞歸里面使用本身sql:
<?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="dao.INewsLabelDao">
<resultMap type="beans.NewsLabel" id="newsLabelMapper">
<id column="id" property="id"/>
<result column="name" property="name"/>
<collection property="children"
ofType="NewsLabel"
select="selectChildByParentId"
column="id"/>
</resultMap>
<select id="selectChildByParentId" resultMap="newsLabelMapper">
select id,name from newslabel where pid=#{xxx}
</select>
</mapper>
測試類MyTest.java:
public class MyTest {
private INewsLabelDao dao;
private SqlSession sqlSession;
@Before
public void Before(){
sqlSession=MyBatisUtils.getSqlSession();
dao=sqlSession.getMapper(INewsLabelDao.class);
}
@Test
public void TestselectMinisterById(){
List<NewsLabel>children=dao.selectChildByParentId(2);
for(NewsLabel newsLabel:children){
System.out.println(newsLabel);
}
}
@After
public void after(){
if(sqlSession!=null){
sqlSession.close();
}
}
}
結(jié)果:
NewsLabel [id=3, name=NBA, children=[NewsLabel [id=5, name=火箭, children=[]], NewsLabel [id=6, name=湖人, children=[]]]]
NewsLabel [id=4, name=CBA, children=[NewsLabel [id=7, name=北京金甌, children=[]], NewsLabel [id=8, name=浙江廣夏, children=[]], NewsLabel [id=9, name=青島雙星, children=[]]]]
這樣的寫法只能選出子孫欄目,不能將自己的信息輸出。
查詢指定目錄以及指定子孫目錄
添加一個(gè)sql的接口:
List<NewsLabel> selectSelfAndChildByParentId(int pid);
mapper文件里面實(shí)現(xiàn),在resultMap里面遞歸調(diào)用另一個(gè)sql,最外層的sql只執(zhí)行一次,這樣就可以實(shí)現(xiàn)查詢自身一次,遞歸查詢子孫欄目的功能:
<!-- 篩選出自己以及子孫欄目-->
<select id="selectChildByParentId2" resultMap="newsLabelMapper2">
select id,name from newslabel where pid=#{ooo}
</select>
<resultMap type="beans.NewsLabel" id="newsLabelMapper2">
<id column="id" property="id"/>
<result column="name" property="name"/>
<collection property="children"
ofType="NewsLabel"
select="selectChildByParentId2"
column="id"/>
</resultMap>
<select id="selectSelfAndChildByParentId" resultMap="newsLabelMapper2">
select id,name from newslabel where id=#{xxx}
</select>
單元測試:
@Test
public void TestselectSelfAndChildrenLabelById(){
List<NewsLabel> children = dao.selectSelfAndChildByParentId(2);
for (NewsLabel newsLabel : children) {
System.out.println(newsLabel);
}
}
結(jié)果:
[service] 2018-07-16 11:17:16,667 - org.apache.ibatis.transaction.jdbc.JdbcTransaction -450 [main] DEBUG org.apache.ibatis.transaction.jdbc.JdbcTransaction - Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@5bb21b69]
[service] 2018-07-16 11:17:16,669 - dao.INewsLabelDao.selectSelfAndChildByParentId -452 [main] DEBUG dao.INewsLabelDao.selectSelfAndChildByParentId - ==> Preparing: select id,name from newslabel where id=?
[service] 2018-07-16 11:17:16,704 - dao.INewsLabelDao.selectSelfAndChildByParentId -487 [main] DEBUG dao.INewsLabelDao.selectSelfAndChildByParentId - ==> Parameters: 2(Integer)
[service] 2018-07-16 11:17:16,722 - dao.INewsLabelDao.selectChildByParentId2 -505 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - ====> Preparing: select id,name from newslabel where pid=?
[service] 2018-07-16 11:17:16,723 - dao.INewsLabelDao.selectChildByParentId2 -506 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - ====> Parameters: 2(Integer)
[service] 2018-07-16 11:17:16,726 - dao.INewsLabelDao.selectChildByParentId2 -509 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - ======> Preparing: select id,name from newslabel where pid=?
[service] 2018-07-16 11:17:16,726 - dao.INewsLabelDao.selectChildByParentId2 -509 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - ======> Parameters: 3(Integer)
[service] 2018-07-16 11:17:16,727 - dao.INewsLabelDao.selectChildByParentId2 -510 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - ========> Preparing: select id,name from newslabel where pid=?
[service] 2018-07-16 11:17:16,728 - dao.INewsLabelDao.selectChildByParentId2 -511 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - ========> Parameters: 5(Integer)
[service] 2018-07-16 11:17:16,729 - dao.INewsLabelDao.selectChildByParentId2 -512 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - <======== Total: 0
[service] 2018-07-16 11:17:16,732 - dao.INewsLabelDao.selectChildByParentId2 -515 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - ========> Preparing: select id,name from newslabel where pid=?
[service] 2018-07-16 11:17:16,732 - dao.INewsLabelDao.selectChildByParentId2 -515 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - ========> Parameters: 6(Integer)
[service] 2018-07-16 11:17:16,733 - dao.INewsLabelDao.selectChildByParentId2 -516 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - <======== Total: 0
[service] 2018-07-16 11:17:16,734 - dao.INewsLabelDao.selectChildByParentId2 -517 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - <====== Total: 2
[service] 2018-07-16 11:17:16,734 - dao.INewsLabelDao.selectChildByParentId2 -517 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - ======> Preparing: select id,name from newslabel where pid=?
[service] 2018-07-16 11:17:16,734 - dao.INewsLabelDao.selectChildByParentId2 -517 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - ======> Parameters: 4(Integer)
[service] 2018-07-16 11:17:16,736 - dao.INewsLabelDao.selectChildByParentId2 -519 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - ========> Preparing: select id,name from newslabel where pid=?
[service] 2018-07-16 11:17:16,736 - dao.INewsLabelDao.selectChildByParentId2 -519 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - ========> Parameters: 7(Integer)
[service] 2018-07-16 11:17:16,738 - dao.INewsLabelDao.selectChildByParentId2 -521 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - <======== Total: 0
[service] 2018-07-16 11:17:16,738 - dao.INewsLabelDao.selectChildByParentId2 -521 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - ========> Preparing: select id,name from newslabel where pid=?
[service] 2018-07-16 11:17:16,739 - dao.INewsLabelDao.selectChildByParentId2 -522 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - ========> Parameters: 8(Integer)
[service] 2018-07-16 11:17:16,741 - dao.INewsLabelDao.selectChildByParentId2 -524 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - <======== Total: 0
[service] 2018-07-16 11:17:16,742 - dao.INewsLabelDao.selectChildByParentId2 -525 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - ========> Preparing: select id,name from newslabel where pid=?
[service] 2018-07-16 11:17:16,742 - dao.INewsLabelDao.selectChildByParentId2 -525 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - ========> Parameters: 9(Integer)
[service] 2018-07-16 11:17:16,743 - dao.INewsLabelDao.selectChildByParentId2 -526 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - <======== Total: 0
[service] 2018-07-16 11:17:16,744 - dao.INewsLabelDao.selectChildByParentId2 -527 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - <====== Total: 3
[service] 2018-07-16 11:17:16,744 - dao.INewsLabelDao.selectChildByParentId2 -527 [main] DEBUG dao.INewsLabelDao.selectChildByParentId2 - <==== Total: 2
[service] 2018-07-16 11:17:16,745 - dao.INewsLabelDao.selectSelfAndChildByParentId -528 [main] DEBUG dao.INewsLabelDao.selectSelfAndChildByParentId - <== Total: 1
NewsLabel [id=2, name=體育新聞, children=[NewsLabel [id=3, name=NBA, children=[NewsLabel [id=6, name=湖人, children=[]], NewsLabel [id=5, name=火箭, children=[]]]], NewsLabel [id=4, name=CBA, children=[NewsLabel [id=7, name=北京金甌, children=[]], NewsLabel [id=8, name=浙江廣夏, children=[]], NewsLabel [id=9, name=青島雙星, children=[]]]]]]
到此這篇關(guān)于Mybatis自關(guān)聯(lián)查詢一對多查詢的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Mybatis 一對多查詢內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot 圖形驗(yàn)證碼的生成和校驗(yàn)
隨著系統(tǒng)和業(yè)務(wù)的不停升級,前后端代碼放在一起的項(xiàng)目越來越臃腫,已經(jīng)無法快速迭代和職責(zé)區(qū)分了,于是紛紛投入了前后端分離的懷抱,發(fā)現(xiàn)代碼和職責(zé)分離以后,開發(fā)效率越來越高了,但是以前的驗(yàn)證碼登錄方案就要更改了。本文來看一下SpringBoot 圖形驗(yàn)證碼的生成和校驗(yàn)2021-05-05
Java組件FileUpload上傳文件實(shí)現(xiàn)代碼
這篇文章主要為大家詳細(xì)介紹了Java組件FileUpload上傳文件實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-06-06
java后臺(tái)如何利用Pattern提取所需字符詳解
這篇文章主要給大家介紹了關(guān)于java后臺(tái)如何利用Pattern提取所需字符的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2022-01-01
mybatis 在typeAliases別名時(shí)報(bào)錯(cuò)的解決
這篇文章主要介紹了mybatis 在typeAliases別名時(shí)報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
maven倉庫中心mirrors配置多個(gè)下載中心(執(zhí)行最快的鏡像)
這篇文章主要介紹了maven倉庫中心mirrors配置多個(gè)下載中心(執(zhí)行最快的鏡像),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07

