mybatis使用collection嵌套查询的实现
作者:luffy5459 发布时间:2021-07-06 22:04:58
在开发中,可能会遇到一对多的关系,这个时候,一条sql语句就难以胜任这个任务了。只能先执行一条sql,然后根据返回的结果,再做一次sql关联查询,这个时候,使用mybatis的collection就可以实现。
如果第一次查询返回的是一个list集合,那么,后续的查询就是一个for循环。所以不使用collection的做法,在java语言中,就要分两次查询。一般而言,我们的列表查询都是分页查询,所以集合数据不会太大,第二次for循环查询效率还好。
下面介绍mybatis使用collection嵌套查询解决这个问题。这里为了简单,以员工与部门的关系来做这个实验,其实员工与部门的关系还应该使用一个中间表来关联,这里只用两张表。
表结构与数据如下所示:
数据:
这里采用maven构建springboot+mybatis-plus+mysql工程。
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
定义的实体:
员工信息:
package com.xxx.springboot.mybatis.domain;
import java.util.List;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("xx_emp")
public class Employee {
private Integer id ;
private String name ;
private int age ;
private List<Department> depts ;
}
部门信息
package com.xxx.springboot.mybatis.domain;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("xx_dept")
public class Department {
private Integer id ;
private String name ;
private Integer userId ;
}
Mapper接口
package com.xxx.springboot.mybatis.mapper;
import org.apache.ibatis.annotations.Mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xxx.springboot.mybatis.domain.Department;
import com.xxx.springboot.mybatis.domain.Employee;
@Mapper
public interface EmpMapper extends BaseMapper<Employee>{
Employee queryByName(String name);
Department queryByUserId(Integer userId);
}
EmpMapper.xml配置文件
<?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="com.xxx.springboot.mybatis.mapper.EmpMapper">
<resultMap id="empMap" type="com.xxx.springboot.mybatis.domain.Employee" >
<id column="id" property="id" />
<result column="name" property="name" />
<result column="age" property="age" />
<collection property="depts" javaType="java.util.ArrayList" ofType="com.xxx.springboot.mybatis.domain.Department"
select="com.xxx.springboot.mybatis.mapper.EmpMapper.queryByUserId" column="{userId=id}"></collection>
</resultMap>
<resultMap id="deptMap" type="com.xxx.springboot.mybatis.domain.Department">
<id column="id" property="id"/>
<result column="name" property="name"/>
<result column="user_id" property="userId"/>
</resultMap>
<select id="queryByName" resultMap="empMap">
SELECT
*
FROM xx_emp
WHERE name = #{name}
</select>
<select id="queryByUserId" resultMap="deptMap">
SELECT
*
FROM xx_dept
WHERE user_id = #{userId}
</select>
</mapper>
测试类:
package com.xxx.springboot;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xxx.springboot.mybatis.domain.Employee;
import com.xxx.springboot.mybatis.mapper.EmpMapper;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MyBatisTest {
@Autowired
private EmpMapper empMapper;
@Test
public void testEmpQuery() {
Employee emp = empMapper.queryByName("aa");
System.out.println(emp);
}
}
运行单元测试,打印信息如下:
这个程序,在第一次根据名称查询员工信息之后,返回id=1,name=aa,age=18,接着,根据id=1 查询了部门表,其实这里的id=1,作为参数传入部门表中,就成了user_id对应的参数,然后就查询出了两个部门记录id=1,id=3,最后打印的员工信息里面,depts就是一个集合。
使用这个嵌套查询,需要注意的是collection有如下属性:
property 实体中对应的属性,这里是depts。 javaType 实体属性的类型,这里是一个集合,所以使用java.util.ArrayList表示。 ofType 集合范型中的类型,这里是部门信息,对应java类Department select 嵌套子查询的ID column 这里最关键,也比较难理解,默认一个参数,可以直接写column = "id",最后根据参数类型匹配。这里其实是传入子查询中的参数,也就是子查询的关联属性user_id对应的参数值,在collection这里就是主sql中查询出来的列值,如果这里id有了别名,比如emp_id,这里就应该写column = "emp_id"。还有一种写法,通过大括号来表示,这种写法可以传入多个参数(多个参数用逗号隔开)。对于本示例而言,正确的写法就是column={userId=id},userId对应 queryByUserId查询语句中 SELECT * FROM xx_dept WHERE user_id = #{userId} 参数userId。id就是主sql查询出来的列id值,就是xx_emp对应的id列值。
我个人在使用collection的时候,大概明白这种嵌套查询的作用,但是就是不明白,怎么传递参数,后来看过一些例子,原来主要点就在column属性这里。
来源:https://blog.csdn.net/feinifi/article/details/124615025


猜你喜欢
- 在Android/Java开发中,用来处理字符串常用的类有3种: String、StringBuilder、StringBuffer。它们的
- 什么是反射?反射是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动
- 本文实例为大家分享了Android ViewPager实现轮播图效果的具体代码,供大家参考,具体内容如下先上一张效果图:说到ViewPage
- 最近做一个C#项目,需要对radis进行读写。首先引入System.Configuration,如下实现代码如下:public class
- 简介本文主要讲解java代码如何利用selenium操作浏览器上传和下载文件代码教程。上传文件常见的 web 页面的上传,一般使用 inpu
- 1.面向接口编程和面向对象编程是什么关系首先,面向接口编程和面向对象编程并不是平级的,它并不是比面向对象编程更先进的一种独立的编程思想,而是
- Spring Security 基本介绍这里就不对Spring Security进行过多的介绍了,具体的可以参考官方文档我就只说下Sprin
- 目录断言对象、数组、集合ObjectUtilsStringUtilsCollectionUtils文件、资源、IO 流FileCopyUti
- 一、使用策略枚举来优化if-else看到网上蛮多人推荐使用策略模式来优化if-else,但我总觉得,搞一堆策略类来优化大批量if-else,
- 如果需要实现跨服务器上传文件,就是将我们本地的文件上传到资源服务器上,比较好的办法就是通过ftp上传。这里是结合SpringMVC+ftp的
- 前言在现实项目中,数据量一般都不小,如果一次性全部请求出来,肯定是影响性能,而且大量数据展示到页面上观感也不好。这时我们就需要用到分页,给定
- 本文要解决在侧滑菜单右边加个文本框,并能实现文本的上下滑动和菜单的左右滚动。这里推荐可以好好看看android的触摸事件的分发机制,这里我就
- 将一个字符串转化成String[]数组,提供两种方法前言将字符串转化成数组提供两种方法:1.split("");2.to
- 最近没做项目,重新整理了一个最完整的Mybatis Generator(简称MBG)的最完整配置文件,带详解,再也不用去看EN的User G
- startJVM是加载jvm用的方法。在JPype,apache mod等等很多地方都用到。但凡要用其他语言来加载jvm进程,就要用到这个。
- 本文为大家分享了Android Studio3安装图文教程,供大家参考,具体内容如下Android Studio及其相关资源下载地址:dow
- 对于maven的部署和安装插件不熟的同学可以看一下上两篇文章maven的部署和安装:此笔记已经集成了maven的插件。一、构建Maven项目
- 本文实例为大家分享了Java实现计算器设计的具体代码,供大家参考,具体内容如下需求分析目的是实现一个基于Java的可以求解带括号加减乘除表达
- 一、Flutter介绍Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。Flutter可以与现
- foreach拼接字符串查询无数据返回Mybatis-plus xml使用foreach遍历查询条件,填充IN函数时,查询不到数据入参 Li