在开发中,可能会遇到一对多的关系,这个时候,一条sql语句就难以胜任这个任务了。只能先执行一条sql,然后根据返回的结果,再做一次sql关联查询,这个时候,使用mybatis的collection就可以实现。
如果第一次查询返回的是一个list集合,那么,后续的查询就是一个for循环。所以不使用collection的做法,在java语言中,就要分两次查询。一般而言,我们的列表查询都是分页查询,所以集合数据不会太大,第二次for循环查询效率还好。
下面介绍mybatis使用collection嵌套查询解决这个问题。这里为了简单,以员工与部门的关系来做这个实验,其实员工与部门的关系还应该使用一个中间表来关联,这里只用两张表。
表结构与数据如下所示:
数据:
这里采用maven构建springboot+mybatis-plus+mysql工程。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
< 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 > |
定义的实体:
员工信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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 ; } |
部门信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
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接口
1
2
3
4
5
6
7
8
9
10
11
12
|
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配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
<? 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 > |
测试类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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嵌套查询内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!
原文链接:https://blog.csdn.net/feinifi/article/details/124615025