经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 数据库/运维 » MyBatis » 查看文章
mybatis使用collection嵌套查询的实现
来源:jb51  时间:2022/5/9 11:07:59  对本文有异议

在开发中,可能会遇到一对多的关系,这个时候,一条sql语句就难以胜任这个任务了。只能先执行一条sql,然后根据返回的结果,再做一次sql关联查询,这个时候,使用mybatis的collection就可以实现。

如果第一次查询返回的是一个list集合,那么,后续的查询就是一个for循环。所以不使用collection的做法,在java语言中,就要分两次查询。一般而言,我们的列表查询都是分页查询,所以集合数据不会太大,第二次for循环查询效率还好。

下面介绍mybatis使用collection嵌套查询解决这个问题。这里为了简单,以员工与部门的关系来做这个实验,其实员工与部门的关系还应该使用一个中间表来关联,这里只用两张表。

表结构与数据如下所示:

数据:

这里采用maven构建springboot+mybatis-plus+mysql工程。

  1. <dependency>
  2. <groupId>com.baomidou</groupId>
  3. <artifactId>mybatis-plus-boot-starter</artifactId>
  4. <version>3.2.0</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>mysql</groupId>
  8. <artifactId>mysql-connector-java</artifactId>
  9. </dependency>
  10. <dependency>
  11. <groupId>org.projectlombok</groupId>
  12. <artifactId>lombok</artifactId>
  13. </dependency>

定义的实体:

员工信息:

  1. package com.xxx.springboot.mybatis.domain;
  2. import java.util.List;
  3. import com.baomidou.mybatisplus.annotation.TableName;
  4. import lombok.Data;
  5. @Data
  6. @TableName("xx_emp")
  7. public class Employee {
  8. private Integer id ;
  9. private String name ;
  10. private int age ;
  11. private List<Department> depts ;
  12. }

部门信息 

  1. package com.xxx.springboot.mybatis.domain;
  2. import com.baomidou.mybatisplus.annotation.TableName;
  3. import lombok.Data;
  4. @Data
  5. @TableName("xx_dept")
  6. public class Department {
  7. private Integer id ;
  8. private String name ;
  9. private Integer userId ;
  10. }

Mapper接口

  1. package com.xxx.springboot.mybatis.mapper;
  2. import org.apache.ibatis.annotations.Mapper;
  3. import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  4. import com.xxx.springboot.mybatis.domain.Department;
  5. import com.xxx.springboot.mybatis.domain.Employee;
  6. @Mapper
  7. public interface EmpMapper extends BaseMapper<Employee>{
  8. Employee queryByName(String name);
  9. Department queryByUserId(Integer userId);
  10. }

EmpMapper.xml配置文件

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  3. <mapper namespace="com.xxx.springboot.mybatis.mapper.EmpMapper">
  4. <resultMap id="empMap" type="com.xxx.springboot.mybatis.domain.Employee" >
  5. <id column="id" property="id" />
  6. <result column="name" property="name" />
  7. <result column="age" property="age" />
  8. <collection property="depts" javaType="java.util.ArrayList" ofType="com.xxx.springboot.mybatis.domain.Department"
  9. select="com.xxx.springboot.mybatis.mapper.EmpMapper.queryByUserId" column="{userId=id}"></collection>
  10. </resultMap>
  11. <resultMap id="deptMap" type="com.xxx.springboot.mybatis.domain.Department">
  12. <id column="id" property="id"/>
  13. <result column="name" property="name"/>
  14. <result column="user_id" property="userId"/>
  15. </resultMap>
  16. <select id="queryByName" resultMap="empMap">
  17. SELECT
  18. *
  19. FROM xx_emp
  20. WHERE name = #{name}
  21. </select>
  22. <select id="queryByUserId" resultMap="deptMap">
  23. SELECT
  24. *
  25. FROM xx_dept
  26. WHERE user_id = #{userId}
  27. </select>
  28. </mapper>

测试类:

  1. package com.xxx.springboot;
  2. import org.junit.Test;
  3. import org.junit.runner.RunWith;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.boot.test.context.SpringBootTest;
  6. import org.springframework.test.context.junit4.SpringRunner;
  7. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  8. import com.xxx.springboot.mybatis.domain.Employee;
  9. import com.xxx.springboot.mybatis.mapper.EmpMapper;
  10. @RunWith(SpringRunner.class)
  11. @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
  12. public class MyBatisTest {
  13. @Autowired
  14. private EmpMapper empMapper;
  15. @Test
  16. public void testEmpQuery() {
  17. Employee emp = empMapper.queryByName("aa");
  18. System.out.println(emp);
  19. }
  20. }

运行单元测试,打印信息如下:

这个程序,在第一次根据名称查询员工信息之后,返回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!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号