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

注:代码已托管在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=[]]]]]]

到此这篇关于Mybatis自关联查询一对多查询的实现示例的文章就介绍到这了,更多相关Mybatis 一对多查询内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Mybatis关联查询之一对多和多对一XML配置详解

    平时在开发过程中dao.bean和XML文件都是自动生成的,很少写XML的配置关系,今天记录一下mybatis的关联查询中的多对一和一对多的情况. 首先是有两张表(学生表Student和老师Teacher表,注:这里只是为了演示一对多和多对一的情况,请不要杠),为了更易懂,这里只设置了最简单的几个必要字段.表结构如下图 Student表: Teacher表: 创建实体bean Teacher.java: import java.util.List; public class Teacher {

  • 解决mybatis一对多关联查询多条数据只显示一条的问题

    一对多,如果多个表字段名相同,要记住使用别名,否则多条数据只显示一条 <resultMap type="com.example.demo.model.TuserModel" id="extendMapper"> <id column="id" property="id" /> <result column="user_name" property="userName&

  • MyBatis一对多嵌套查询的完整实例

    前言 嵌套查询的实现原理为两次查询,比如产品表为主表,图片表为从表通过product_id字段与产品表id字段关联实现一对多,嵌套查询 首先查询 主表的数据 然后将主表id字段赋值给从表实体类中product_id 字段(productId)然后通过dao接口路径映射找到对应的MyBatis XMl文件SQL语句ID如:com.liao.dao.DImgMapper.selectDImgByProductId 进行子查询也就是第二次查询.然后返回数据 数据库建表语句和测试数据如下: 数据库版本为

  • 解决mybatis plus 一对多分页查询问题

    最近用mybatis plus做项目,单表的增删改查都正常,做到 1对多表的分页时,用resultMap返回的时候发现返回的记录和总数对不上 返回的记录是 一 表的,二返回的总数是 多 表 查了一下,这个或者是PLUS的bug 大概的解决办法如下图:用collection,传参用column,我这里用了一个小技巧, 把外面传入的参数,作为主表的column传入到从表. 这里没找到其他方法,有其他方法可以评论告诉我 补充知识:解决Mybatis-plus利用collection查询一对多分页数据的

  • mybatis高级映射一对多查询实现代码

    1.需求分析: 在开发中会遇到这样一个问题,查询订单信息,级联查询出用户信息和订单明细信息 2.sql语句实现 2.1确定主查询表:订单表 2.2确定关联查询表:用户表, 订单明细表 sql语句如下: select orders.*, t_user.address, t_user.name, t_user.brithday, orderdetail.id orderdetail_id, orderdetail.orderid, orderdetail.itemsid from orders, t

  • Mybatis 一对多和多对一关联查询问题

    首先  数据库量表之间字段关系(没有主外键) studentmajor表的id字段对应student表里major字段 两个实体类 package com.model; import java.util.Date; public class Student { private Integer sno; private String sname; private String ssex; private Integer sclass; private StudentMajor studentmaj

  • mybatis 一对一、一对多和多对多查询实例代码

    关键字:association 一对一映射(一个班级只有一个班主任) <select id="getClass" parameterType="int" resultMap="ClassesResultMap"> select * from class c,teacher t where c.teacher_id=t.t_id and c.c_id=#{id} </select> <resultMap type=&q

  • mybatis一对多查询功能

    首先,我们还是先给出一个需求:根据订单id查询订单明细--我们知道,一个订单里面可以有多个订单的明细(需求不明确的同学,请留言或者去淘宝网上的订单处点一下就知道了).这个时候,一个订单,对应多个订单的id.这种需求出现的时候,我们应该如何查询呢? 此时我们的数据模型如下图(左)由于查询用户也是我们的需求,所以就在原有的基础上进行扩展,数据模型如下(右): 很显然,如果用resultType的方式去实现的话,是不合理的了.因为我们需要创建一个既有订单又有订单明细的pojo然后呢,我们的mybati

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

    注:代码已托管在GitHub上,地址是:https://github.com/Damaer/Mybatis-Learning ,项目是mybatis-13-oneself-one2many,需要自取,需要配置maven环境以及mysql环境(sql语句在resource下的test.sql中),觉得有用可以点个小星星. docsify文档地址在:https://damaer.github.io/Mybatis-Learning/#/ 所谓自关联查询,是指自己既然充当一方,又充当多方.比如新闻栏目

  • 关于mybatis一对一查询一对多查询遇到的问题

    springboot整合mybatis项目博客系统文章,相册,评论,标签,等表IDEA为最新版2021.3.3,mysql数据库为最新版Navicat(或许有些字段不支持特定的命名) 也是醉了,以前idea还是19版的,navicat也是老版本的时候mybatis关联查询mapper操作能正常运行,拿到相应字段,并封装,但最近写项目过程中遇到一个离谱的是,过了好久才发现, 当关联查询时,无论一对一还是一对多除了需要注意javaType和ofType之外,还应该注意各表主键不能同一名称 实体类文章

  • MyBatis图文并茂讲解注解开发一对多查询

    目录 MyBatis的注解实现复杂映射开发 一对多查询 一对多查询的模型 一对多查询的语句 创建StudentMapper接口 使用注解配置Mapper 测试类 一对多配置总结 MyBatis的注解实现复杂映射开发 实现复杂关系映射之前我们可以在映射文件中通过配置来实现,使用注解开发后,我们可以使用@Results注解,@Result注解,@One注解,@Many注解组合完成复杂关系的配置 一对多查询 一对多查询的模型 一对多查询的需求:查询一个课程,与此同时查询出该该课程对应的学生信息 一对多

  • Mybatis一对多查询的两种姿势(值得收藏)

    前言 最近碰到了Mybatis一对多查询的场景,在这里总结对比下常见的两种实现方式. 本文以常见的订单表和订单详情表来举例说明: 数据库表准备 订单表 tbl_order 订单详情表 tlb_order_detail ps: 一个订单关联多个订单详情,通过order_no订单号关联: 实例演示 方法一:联合查询ResultMap映射 sql直接关联查询,然后结果集通过resultMap的collection映射 例如 查询订单列表,包括订单详情 Order.java 中新增字段orderDeta

  • mybatis通过中间表实现一对多查询功能

    需求: 通过一个学生的id查询出该学生所学的所有科目. 使用到的表格: 1.student:学生表 2.subject:科目表 3.stu_sub:学生-科目表(这里的成绩字段没用到,不用管) 实体类( get.set方法省略): 1.student public class Student implements Serializable { private int id; private String stuNum; //学号 private String password; private

  • MybatisPlus实现对象嵌套关联查询一对多List集合查询

    目录 对象嵌套关联查询一对多List集合查询 mybatis嵌套关联查询如下 一对多查询(经典案例) 条件 数据库 代码实现 对象嵌套关联查询一对多List集合查询 mybatis嵌套关联查询如下 由于我的是一对集合查询,所以我有两个类. @Data @TableName("tb_user") public class User {     @TableId(type= IdType.INPUT)     private String id;     @TableField("

  • MySQL 多表关联一对多查询实现取最新一条数据的方法示例

    本文实例讲述了MySQL 多表关联一对多查询实现取最新一条数据的方法.分享给大家供大家参考,具体如下: MySQL 多表关联一对多查询取最新的一条数据 遇到的问题 多表关联一对多查询取最新的一条数据,数据出现重复 由于历史原因,表结构设计不合理:产品告诉我说需要导出客户信息数据,需要导出客户的 所属行业,纳税性质 数据:但是这两个字段却在订单表里面,每次客户下单都会要求客户填写:由此可知,客户数据和订单数据是一对多的关系:那这样的话,问题就来了,我到底以订单中的哪一条数据为准呢?经过协商后一致同

  • springboot整合mybatis实现简单的一对多级联查询功能

    本文的目的是用springboot整合mybatis实现一个简单的一对多查询.(查询一个用户有多少件衣服) 第一步:数据库中,可以直接在navicat中建立两张我们需要用到的表 users DROP TABLE IF EXISTS `users`; CREATE TABLE `users` ( `id` int(0) NOT NULL AUTO_INCREMENT, `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_

随机推荐