Spring Boot (11) mybatis 关联映射
一对多
查询category中的某一条数据,同时查询该分类下的所有Product。
Category.java
public class Category {
private Integer id;
private String name;
private List<Product> product;
....
product.java
public class Product {
private Integer id;
private String name;
private String price;
private Integer categoryId;
...
dao层
@Mapper
public interface MyBatisDao { @Select("select * from product where categoryId = #{categoryId}")
List<Product> findProductByCategoryId(Integer categoryId); @Results({
@Result(property = "id" , column = "id"),
//products映射<List> Product,many=@Many是调用关联的方法,"id"是关联的条件, FetchType.LAZY是延迟加载
@Result(property = "products", column = "id", many=@Many(select = "com.david.dao.MyBatisDao.findProductByCategoryId",fetchType = FetchType.LAZY))
})
@Select("select * from category where id = #{id}")
Category findCategoryById(Integer id); }
service层
@Service
@Transactional
public class MyBatisService { @Resource
private MyBatisDao myBatisDao; public Category findCategoryById(){
Category category = myBatisDao.findCategoryById(1);return category;
} }
测试:


一对一:把上面的@many=@Many换成one=@One即可
修改Product.java 增加属性
public class Product {
private Integer id;
private String name;
private String price;
private Integer categoryId;
private Category category;
dao
@Results({
@Result(property = "id", column = "id"),
@Result(property = "category", column = "categoryId",one=@One(select = "com.david.dao.MyBatisDao.findCategoryById",fetchType = FetchType.LAZY))
})
@Select("select * from Product where id = #{id}")
Product findProductCategoryById(Integer id);
多对多:把多个字段映射成many=@Many即可
多对一:把上面dao方法的返回值从Category改成List<Category>
JAVA注解的局限性
返回多条Category
@Results({
@Result(property = "id" , column = "id"),
//products映射<List> Product,many=@Many是调用关联的方法,"id"是关联的条件, FetchType.LAZY是延迟加载
@Result(property = "products", column = "id", many=@Many(select = "com.david.dao.MyBatisDao.findProductByCategoryId",fetchType = FetchType.LAZY))
})
@Select("select * from category")
List<Category> findAllCategory();
category现在有三条记录,我要查出所有category及其对应的product,最终得到一个List<Category> 查询过程是这样的:


一共执行了四次查询,一次查category表,因为有三条记录,所以查了三次product表,以此来填充三个List<Product> products属性。如果category中又几百条数据,而且还有上十个表进行关联查询,结果无法想象。在传统的xml配置中,是可以用一条sql语句查出来的,不过mybatis官方做出了一个说明,由于java注解的局限性,不支持那种映射方式。所以,如果只想用一条sql语句查出关联映射,必须借助xml。
xml无限层嵌套映射
这里以三层嵌套为例,实现前端的三级菜单树。这是一个tree表,pid是其上级菜单的id。

要得到查询结果Tree对象,这个对象是可以无限递归的
public class TreeMenu {
private Integer Id;
private String MenuName;
private List<TreeMenu> child;
dao
@Mapper
public interface TreeMenuDao {
@ResultMap("treeMenu")
@Select("select p1.id,p1.menuName,p2.id id2,p2.menuName menuName2,p3.id id3,p3.menuName menuName3"+
"from treemenu p1, treemenu p2,treemenu p3 where p1.id = p2.pid and p2.id = p3.pid")
List findTreeMenu();
}
这个sql语句在数据库中查询结果是这样的,可以发现前四个字段是一样的,而且都是冗余数据,如果用java注解的关联查询是不会这样的

@ResultMap("treeMenu"):映射结果集id是treeMenu,这个映射要在xml中配置
application.yml中添加配置
mybatis:
mapper-locations: classpath:mapper/*
在resources/mapper/TreeMenuMapper.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">
<!-- 映射dao -->
<mapper namespace="com.david.dao.TreeMenuDao">
<!-- 结果集类型 -->
<resultMap id="treeMenu" type="com.david.bean.TreeMenu">
<!-- 映射字段 -->
<result column="Id" property="Id" />
<result column="MenuName" property="MenuName" />
<!-- 嵌套第二张表 -->
<collection property="child" ofType="com.david.bean.TreeMenu" >
<id column="Id2" property="Id" />
<result column="MenuName2" property="MenuName" />
<!-- 嵌套第三张表 -->
<collection property="child" ofType="com.david.bean.TreeMenu" >
<id column="Id3" property="Id" />
<result column="MenuName3" property="MenuName" />
</collection>
</collection>
</resultMap>
</mapper>
这里只是配置一个嵌套映射,在dao方法中通过@ResultMap("treeMenu")使用这个映射。最终查询结果会映射成一个TreeMenu对象,通过spring mvc转换为json结果如下,在一些前端框架中,实现属性菜单就是需要用这种结构的json数据值。
[
{
"child": [
{
"child": [
{
"child": null,
"id": 4,
"menuName": "三级菜单-1-1"
},
{
"child": null,
"id": 5,
"menuName": "三级菜单-1-2"
}
],
"id": 2,
"menuName": "二级菜单-1"
},
{
"child": [
{
"child": null,
"id": 6,
"menuName": "三级菜单-2-1"
}
],
"id": 3,
"menuName": "二级菜单-2"
}
],
"id": 1,
"menuName": "一级菜单"
}
]
Spring Boot (11) mybatis 关联映射的更多相关文章
- spring boot(9)-mybatis关联映射
一对多 查询type表的某一条数据,并且要同时查出所有typeid与之配置的user,最终要得到一个以下类型的Type对象 public class Type { String id; String ...
- 【spring boot】14.spring boot集成mybatis,注解方式OR映射文件方式AND pagehelper分页插件【Mybatis】pagehelper分页插件分页查询无效解决方法
spring boot集成mybatis,集成使用mybatis拖沓了好久,今天终于可以补起来了. 本篇源码中,同时使用了Spring data JPA 和 Mybatis两种方式. 在使用的过程中一 ...
- Spring Boot整合Mybatis完成级联一对多CRUD操作
在关系型数据库中,随处可见表之间的连接,对级联的表进行增删改查也是程序员必备的基础技能.关于Spring Boot整合Mybatis在之前已经详细写过,不熟悉的可以回顾Spring Boot整合Myb ...
- Spring Boot 整合 Mybatis 实现 Druid 多数据源详解
摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! “清醒时做事,糊涂时跑步,大怒时睡觉,独处时思考” 本文提纲一.多数据源的应用场景二.运行 sp ...
- Spring Boot整合Mybatis并完成CRUD操作
MyBatis 是一款优秀的持久层框架,被各大互联网公司使用,本文使用Spring Boot整合Mybatis,并完成CRUD操作. 为什么要使用Mybatis?我们需要掌握Mybatis吗? 说的官 ...
- Spring boot教程mybatis访问MySQL的尝试
Windows 10家庭中文版,Eclipse,Java 1.8,spring boot 2.1.0,mybatis-spring-boot-starter 1.3.2,com.github.page ...
- Spring Boot集成MyBatis开发Web项目
1.Maven构建Spring Boot 创建Maven Web工程,引入spring-boot-starter-parent依赖 <project xmlns="http://mav ...
- 详解Spring Boot集成MyBatis的开发流程
MyBatis是支持定制化SQL.存储过程以及高级映射的优秀的持久层框架,避免了几乎所有的JDBC代码和手动设置参数以及获取结果集. spring Boot是能支持快速创建Spring应用的Java框 ...
- spring boot配置mybatis和事务管理
spring boot配置mybatis和事务管理 一.spring boot与mybatis的配置 1.首先,spring boot 配置mybatis需要的全部依赖如下: <!-- Spri ...
随机推荐
- DOCKER - POD操作
强制删除 Terminating 的pod kubectl delete -n <namespace> <pod podname> --grace-period=0 --fo ...
- 1、DataGridView
DataGridView赋值后 通过RowPostPaint事件绘制行号 private void AddXh() { DataGridViewTextBoxColumn col = new Data ...
- 洛谷——P2341 [HAOI2006]受欢迎的牛//POJ2186:Popular Cows
P2341 [HAOI2006]受欢迎的牛/POJ2186:Popular Cows 题目背景 本题测试数据已修复. 题目描述 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就是一头明星奶牛.所 ...
- Scrapy爬虫框架示意图汇总
- Nodejs介绍及其安装
一.Nodejs介绍 Nodejs英文网:https://nodejs.org/en/ Nodejs中文网:http://nodejs.cn/ Node.js 是一个基于 Chrome V8 引擎的 ...
- CTF实战(隐写术):欢迎来到地狱
前言:请登录实验吧开启刷题模式,拿到的flag返回该网站验证正确性. 下载“欢迎来到地狱”CTF题目(总共三个文件
- Emacs的undo与redo
在Emacs的手册16.1节中有这样一句话, Any command other than an undo command breaks the sequence of undo commands. ...
- 6.3.3 使用 shelve 模块操作二进制文件
Python标准库shelve也提供了二进制文件操作的功能,可以像字典赋值一样来写入二进制文件,也可以像字典一样读取二进制文件,有点类似于NoSQL数据库MongoDB. import shelve ...
- 3.3.4 lambda 表达式
lambda表达式常用来声明匿名函数,即没有函数名字的临时使用的小函数,例如第2章中列表对象的sort()方法以及内置函数sorted()中key参数.lambda表达式只可以包含一个表达式,不允许包 ...
- scp相关命令总结
scp 跨机远程拷贝scp是secure copy的简写,用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的.当你服务器硬盘 ...