欢迎访问我的GitHub

https://github.com/zq2599/blog_demos

内容:所有原创文章分类汇总及配套源码,涉及Java、Docker、Kubernetes、DevOPS等;

本篇概览

本文是《MyBatis初级实战》系列的第六篇,继续实践从多表获取数据;

回顾上一篇,咱们实战了多表关联的一对一关系,如下图所示,查找日志记录时,把对应的用户信息查出:

本篇要实践的是一对多关系:查询用户记录时,把该用户的所有日志记录都查出来,逻辑关系如下图:

在具体编码实现一对多查询时,分别使用联表和嵌套两种方式实现,每种方式都按照下图的步骤执行:

源码下载

如果您不想编码,可以在GitHub下载所有源码,地址和链接信息如下表所示(https://github.com/zq2599/blog_demos):

名称

链接

备注

项目主页

https://github.com/zq2599/blog_demos

该项目在GitHub上的主页

git仓库地址(https)

https://github.com/zq2599/blog_demos.git

该项目源码的仓库地址,https协议

git仓库地址(ssh)

git@github.com:zq2599/blog_demos.git

该项目源码的仓库地址,ssh协议

这个git项目中有多个文件夹,本章的应用在mybatis文件夹下,如下图红框所示:

3. mybatis是个父工程,里面有数个子工程,本篇的源码在relatedoperation子工程中,如下图红框所示:

准备数据

本次实战,在名为mybatis的数据库中建立两个表(和前面几篇文章中的表结构一模一样):user和log表;

user表记录用户信息,非常简单,只有三个字段:主键、名称、年龄

log表记录用户行为,四个字段:主键、用户id、行为描述、行为时间

user和log的关系如下图:

5. 建表和添加数据的语句如下:

use mybatis;DROP TABLE IF EXISTS `user`;CREATE TABLE `user` ( `id` int(32) NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL, `age` int(32) NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;DROP TABLE IF EXISTS `log`;CREATE TABLE `log` ( `id` int(32) NOT NULL AUTO_INCREMENT, `user_id` int(32), `action` varchar(255) NOT NULL, `create_time` datetime not null, PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;INSERT INTO mybatis.user (id, name, age) VALUES (3, 'tom', 11);INSERT INTO mybatis.log (id, user_id, action, create_time) VALUES (3, 3, 'read book', '2020-08-07 08:18:16');INSERT INTO mybatis.log (id, user_id, action, create_time) VALUES (4, 3, 'go to the cinema', '2020-09-02 20:00:00');INSERT INTO mybatis.log (id, user_id, action, create_time) VALUES (5, 3, 'have a meal', '2020-10-05 12:03:36');INSERT INTO mybatis.log (id, user_id, action, create_time) VALUES (6, 3, 'have a sleep', '2020-10-06 13:00:12');INSERT INTO mybatis.log (id, user_id, action, create_time) VALUES (7, 3, 'write', '2020-10-08 09:21:11');

关于多表关联查询的两种方式

多表关联查询的实现有联表和嵌套查询两种,它们的差异在Mybatis中体现在resultMap的定义上:

联表时,resultMap内使用collection子节点,将联表查询的结果映射到关联对象集合;

嵌套时,resultMap内使用association子节点,association的select属性触发一次新的查询;

上述两种方式都能成功得到查询结果,接下来逐一尝试;

联表查询

本篇继续使用上一篇中创建的子工程relatedoperation;

实体类UserWithLogs.java如下,可见成员变量logs是用来保存该用户所有日志的集合:

package com.bolingcavalry.relatedoperation.entity;import io.swagger.annotations.ApiModel;import io.swagger.annotations.ApiModelProperty;import lombok.Data;import lombok.NoArgsConstructor;import java.util.List;@Data@NoArgsConstructor@ApiModel(description = "用户实体类(含行为日志集合)")public class UserWithLogs { @ApiModelProperty(value = "用户ID") private Integer id; @ApiModelProperty(value = "用户名", required = true) private String name; @ApiModelProperty(value = "用户地址", required = false) private Integer age; @ApiModelProperty(value = "行为日志", required = false) private List logs;}

保存SQL的UserMapper.leftJoinResultMap的resultMap中处理:

leftJoinResultMap这个resultMap是一对多的关键,里面的collection将log的所有记录映射到logs集合中:

接口定义UserMapper.java :

@Repositorypublic interface UserMapper { UserWithLogs leftJoinSel(int id);}

service层:

@Servicepublic class UserService { @Autowired UserMapper userMapper; public UserWithLogs leftJoinSel(int id) { return userMapper.leftJoinSel(id); }}

controller层的代码略多,是因为想把swagger信息做得尽量完整:

@RestController@RequestMapping("/user")@Api(tags = {"UserController"})public class UserController { @Autowired private UserService userService; @ApiOperation(value = "根据ID查找user记录(包含行为日志),联表查询", notes="根据ID查找user记录(包含行为日志),联表查询") @ApiImplicitParam(name = "id", value = "用户ID", paramType = "path", required = true, dataType = "Integer") @RequestMapping(value = "/leftjoin/{id}", method = RequestMethod.GET) public UserWithLogs leftJoinSel(@PathVariable int id){ return userService.leftJoinSel(id); }}

最后是单元测试,在前文创建的ControllerTest.java中新建内部类User用于user表相关的单元测试,可见封装了一个私有方法queryAndCheck负责请求和验证结果,后面的嵌套查询也会用到:

@Nested @TestMethodOrder(MethodOrderer.OrderAnnotation.class) @DisplayName("用户服务") class User { /** * 通过用户ID获取用户信息有两种方式:left join和嵌套查询, * 从客户端来看,仅一部分path不同,因此将请求和检查封装到一个通用方法中, * 调用方法只需要指定不同的那一段path * @param subPath * @throws Exception */ private void queryAndCheck(String subPath) throws Exception { String queryPath = "/user/" + subPath + "/" + TEST_USER_ID; log.info("query path [{}]", queryPath); m.........

java关联查询实战_MyBatis初级实战之六:一对多关联查询相关推荐

  1. ideal新建springboot工程_MyBatis初级实战之一:Spring Boot集成

    欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...

  2. java实现多对多关系的方法_Hibernate一对多关联双向关联代码实现分享

    1.创建实体类(Customer.java.Orders.java) package wck.stu.vo.oneToMany_single; import java.util.HashSet; im ...

  3. 【Mybatis】 mapper XML 文件中使用 collection实现一对多关联

    前言 Mybatis 一对一,使用 association 标签 Mybatis 一对多,使用 collection 标签 本文主要说明 collection 实现一对多关联.使用 associati ...

  4. java+mysql性能优化_Java培训实战教程之mysql优化

    Java培训实战教程之mysql优化 更新时间:2015年12月29日13时30分 来源:传智播客Java培训学院 浏览次数: 1.   mysql引擎 1.1.  引擎类型 MySQL常用的存储引擎 ...

  5. solr模糊查询_《Solr实战》之一

    本文记录笔者在阅读<Solr实战>的读书笔记,将笔者认为重要的内容摘录出来. Solr擅长处理的数据类型 以文本为中心 读主导 文档被读取的次数远大于被创建和更新的次数 面向文档 灵活的模 ...

  6. Java并发编程实战_阿里P9整理分享的亿级流量Java高并发与网络编程实战PDF

    前言 为了帮助初级开发者快速掌握高并发.网络编程.微服务.海量数据的处理这些实用技术,本文以"理论+范例"的形式对各个知识点进行了详细的讲解,力争让读者在实践中快速掌握相关知识. ...

  7. Python和Java结合的项目实战_[项目实战] Python高级教程项目实战篇 Python和Java结合的项目实战 视频教程 [...

    资源介绍 课程简介:xa0xa0 Python高级教程项目实战篇 Python和Java结合的项目实战 视频教程 教学视频 ----------------------课程目录 Python项目实战篇 ...

  8. 企业级系统应用,高级组合查询示例讲解 - Jeecg实战

    企业级系统应用,高级组合查询示例讲解 - Jeecg实战   ---数据多维度查询 经常会有人问:JEECG高级查询怎么用,实现机制是怎样的? 今天为大家揭开这层面纱,让大家了解实质,使用它更快速的构 ...

  9. Java架构-高并发的解决实战总结方案

    Java架构-高并发的解决实战总结方案 1.应用和静态资源分离 刚开始的时候应用和静态资源是保存在一起的,当并发量达到一定程度的时候就需要将静态资源保存到专门的服务器中,静态资源主要包括图片.视频.j ...

  10. java search 不能使用方法_ElasticSearch实战系列三: ElasticSearch的JAVA API使用教程

    前言 在上一篇中介绍了ElasticSearch实战系列二: ElasticSearch的DSL语句使用教程---图文详解,本篇文章就来讲解下 ElasticSearch 6.x官方Java API的 ...

最新文章

  1. mongo在哪创建管理员_如何给mongodb管理员权限
  2. 手动安装boost库
  3. python中的装饰器和抽象类
  4. 最近失业,不知道干什么好,随便乱写,无内容。
  5. EMLOG仿微信主题模板V3.11
  6. C/C++语言传参、返回参数知识点讲解
  7. Graphviz 绘制流程图
  8. opencv-Mat数据类型及位数总结
  9. android:src app:srccompat,android – 数据绑定与srcCompat
  10. java创建实体 内存_加载Java实体时内存不足
  11. MaxScript读取excel数据
  12. StringBuilder和StringBuffer的效率比较
  13. 大数据人工智能行业技术图谱
  14. 芯片短缺:今年圣诞节PS5货量恐不足
  15. Django工程中,pycharm运行manage.py,提示8000端口占用问题error:That port is already in use
  16. git clone https 克隆失败解决办法
  17. 新概念英语(第四册,旧版)复习(原文及全文翻译)——Lesson 1 - Finding Fossil Man(寻找化石人)
  18. Java调用opencv实现图片去水印
  19. MIMIC IV数据库安装(二)
  20. stable_sort的用法与排序算法

热门文章

  1. 97. PATH_SEPARATOR 和 DIRECTORY_SEPARATOR
  2. java 静态成员 概念_Java成员变量、局部变量、静态变量、成员方法、全局方法等概念的区别...
  3. Kubernetes实战阅读笔记--1、介绍
  4. Remap 后的 USART1 不能发送数据
  5. JS重要知识点总结-不完善
  6. swift-自定义Alert
  7. 【Python】django安装
  8. MVC3的新特性介绍
  9. 那年,寻找工作的历程
  10. FireFox2和FireFox3共存解决方案(附完整图解)