Mybatis自关联查询一对多查询的实现示例
作者:秦怀杂货店 发布时间:2021-08-21 04:06:16
注:代码已托管在GitHub上,地址是:https://github.com/Damaer/Mybatis-Learning ,项目是mybatis-13-oneself-one2many,需要自取,需要配置maven环境以及mysql环境(sql语句在resource下的test.sql中),觉得有用可以点个小星星。
docsify文档地址在:https://damaer.github.io/Mybatis-Learning/#/
所谓自关联查询,是指自己既然充当一方,又充当多方。比如新闻栏目的数据表,自己可以是父栏目,也可以是多方,子栏目。在数据表里面实现就是一张表,有一个外键pid,用来表示该栏目的父栏目,一级栏目没有父栏目的,可以将其外键设置为0。
DB表如下:
查询指定栏目的所有子孙栏目
查询指定目录的所有子孙目录,我们需要使用递归的思想,查出当前栏目之后,需要将当前栏目的id作为下一级栏目的pid。
实体类NewsLabel.java,使用一对多的关系:
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();
}
}
}
结果:
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=[]]]]
这样的写法只能选出子孙栏目,不能将自己的信息输出。
查询指定目录以及指定子孙目录
添加一个sql的接口:
List<NewsLabel> selectSelfAndChildByParentId(int pid);
mapper文件里面实现,在resultMap里面递归调用另一个sql,最外层的sql只执行一次,这样就可以实现查询自身一次,递归查询子孙栏目的功能:
<!-- 筛选出自己以及子孙栏目-->
<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);
}
}
结果:
[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=[]]]]]]
来源:https://segmentfault.com/a/1190000039134263


猜你喜欢
- 本文研究的主要是Java中finally和return的关系,具体介绍和实例如下所示。finally 和 return 关系的总结1.try
- 我们都知道可以用爬虫来找寻一些想要的数据,除了可以使用python进行操作,我们最近学习的java同样也支持爬虫的运行,本篇小编就教大家用j
- 一、声明式这种方法不需要对原有的业务做任何修改,通过在XML文件中定义需要拦截方法的匹配即可完成配置,要求是,业务处理中的方法的命名要有规律
- 使用java制作一款简单的扫雷游戏,供大家参考,具体内容如下import java.util.*;public class nephelok
- 栅栏类似闭锁,但是它们是有区别的.1.闭锁用来等待事件,而栅栏用于等待其他线程.什么意思呢?就是说闭锁用来等待的事件就是countDown事
- 一、简介上篇介绍了一个自己做的管理系统,最近空闲的时间自己在继续做,把之前登录时候自定义的 * 过滤器换成了基于SpringSecurity
- 如果没有安装过maven,是用的idea自带的maven,那就是idea的安装目录下 /plugins/maven/lib/maven3这个
- 概述ReentrantReadWriteLock不知道大家熟悉吗?其实在实际的项目中用的比较少,反正我所在的项目没有用到过。Reentran
- 因为项目需要,需要在一个之前没做过springBoot项目的eclipse上跑一个springBoot项目并完成打包,所以就在网上查完资料以
- 本篇使用java自带的MessageDigest实现对文本的md5加密算法,具体代码如下: /** *@Description
- 一、效果实现二、实现思路:1. 正上方的提示区域,用一个类(LockIndicator.java)来实现,自定义view来绘制9个提示图标;
- org.junit.jupiter.api不存在解决方案spring boot2.2之后和之前的测试类编写方法不一致修改为:// A cod
- 本文实例为大家分享了Unity实现全屏截图、Unity实现QQ截图,供大家参考,具体内容如下全屏截图:要实现的是点击鼠标左键,就实现截图,并
- Android 应用签名的两种方法一、使用pem签名 (一) apk签名命令java –jar sign
- 在安全卫生上,经常看到有圆形的进度条在转动,效果非常好看,于是就尝试去实现一下,具体实现过程不多说了,直接上效果图,先炫耀下。效果图:分析:
- 文件输出为字符串示例代码:/** * 读取文件为字符串 * * @return */pub
- 前端使用的是vue+elementui,这款系统只适合学习巩固SpringBoot+VUE,后面还要在这上面加校园公告、校园零食等功能,后期
- C# 解析 jsonJSON(全称为JavaScript Object Notation) 是一种轻量级的数据交换格式。它是基于JavaSc
- 在java.lang.Runtime.exec的使用中,我们经常会用到将重定向命令执行的输入/结果或者将错误信息读取出来.那么,在使用过程中
- 部分情况下无法通过maven仓库直接下载需要的jar包,只能讲jar包下载至本地来使用,spring boot框架内通过maven加载第三方