mybatis使用collection嵌套查询
Posted luffy5459
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mybatis使用collection嵌套查询相关的知识,希望对你有一定的参考价值。
在开发中,可能会遇到一对多的关系,这个时候,一条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属性这里。
创作打卡挑战赛 赢取流量/现金/CSDN周边激励大奖以上是关于mybatis使用collection嵌套查询的主要内容,如果未能解决你的问题,请参考以下文章
【Mybatis】collection一对多查询子查询集合不为空,但属性值为空