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表如下:

Mybatis自关联查询一对多查询的实现示例

查询指定栏目的所有子孙栏目

查询指定目录的所有子孙目录,我们需要使用递归的思想,查出当前栏目之后,需要将当前栏目的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

标签:Mybatis,一对多,查询
0
投稿

猜你喜欢

  • C#微信开发之微信公众号标签管理功能

    2023-04-17 20:20:44
  • C#多线程实现异步接口

    2023-09-09 04:58:52
  • Android利用LitePal操作数据库存取图片

    2021-06-14 14:57:45
  • Java Maven settings.xml中私有仓库配置详解

    2022-02-19 15:36:50
  • springboot 打包部署 共享依赖包(分布式开发集中式部署微服务)

    2022-12-26 09:13:43
  • springboot项目如何防止XSS攻击

    2021-10-17 10:03:02
  • 一篇文章带你深入了解javaIO基础

    2022-10-22 21:43:05
  • java对ArrayList排序代码示例

    2023-11-24 20:14:21
  • spring 整合mybatis后用不上session缓存的原因分析

    2021-12-09 10:11:03
  • Android View 事件分发机制详解

    2023-11-26 05:18:13
  • Spring源码解析之BeanPostProcessor知识总结

    2022-04-07 22:13:34
  • 用C#生成不重复的随机数的代码

    2023-03-08 03:36:52
  • java中如何执行xshell命令

    2021-10-06 16:22:18
  • C# 设计模式系列教程-模板方法模式

    2022-03-17 18:00:15
  • SpringBoot @NotBlank错误的解决方案

    2023-01-12 20:05:59
  • C#对二进制数据进行base64编码的方法

    2023-09-02 23:26:12
  • Android串口通讯SerialPort的使用详情

    2022-03-08 00:23:46
  • Java多线程死锁示例

    2022-09-17 15:05:25
  • 详解Java Streams 中的异常处理

    2021-09-03 11:26:11
  • Flutter中http请求抓包的完美解决方案

    2023-08-22 18:47:47
  • asp之家 软件编程 m.aspxhome.com