在开发中,可能会遇到一对多的关系,这个时候,一条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属性这里。
到此这篇关于mybatis使用collection嵌套查询的实现的文章就介绍到这了,更多相关mybatis collection嵌套查询内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!