一对多

查询type表的某一条数据,并且要同时查出所有typeid与之配置的user,最终要得到一个以下类型的Type对象
public class Type {
String id;
String name;
List<User> users;

dao层

	@Select("select * from user where typeid = #{typeid}")
public List<User> findUserById(String typeid); @Results({
@Result(property="id",column="id"),
//users映射List<User> users,many=@Many是调用关联查询方法,"id"是关联查询条件,FetchType.LAZY是延迟加载
@Result(property="users",column="id", many=@Many(select="hello.dao.MybatisDao.findUserById",fetchType=FetchType.LAZY))
})
@Select("select * from type where id=#{id}")
public Type findTypeById(String id);
注意,如果省略第一个@Result, 查出来的type对象id是null,因为第二个@Result使用关联查询时把column="id"映射给了property="users"。
service层
		Type type = mybatisDao.findTypeById("1");
System.out.println("延迟加载");
type.getUsers();



因为设置了fetchType=FetchType.LAZY,mybatisDao.findTypeById("1")只会查询type表,当访问type.getUsers()时才会查询其关联表。

其它关联

一对一:把上面的many=@Many换成one=@One,其他原理是一样的

多对多:把多个字段映射成many=@Many,就是多对多了

多对一:把上面dao方法的返回值从Type换成List<Type>

JAVA注解的局限性

通过SQL日志可以看到,前面的一对多关联查询实际上执行了两次select,这就是hibernate中典型的n+1问题。
假设我现在type表中有三条记录,我要查出所有的type及其对应的user对象,最终得到一个List<Type>,查询过程是这样的

一共执行了四次查询,一次查type表,因为有三条记录,所以查了三次user表,以此来填充三个type对象的List<User> users属性。如果type表中有几百条数据,而且还有上十个表进行关联查询,结果无法设想。在传统的xml配置方式中,是可以用一条SQL查出无限层嵌套的关联关系的。不过mybatis官方做出了一个说明,由于java注解的局限性,不支持那种映射方式。所以,如果想只用一条SQL查出关联映射,必须借住xml

xml无限层嵌套映射

这里以三层嵌套为例,以实现前端的三级菜单树。这是一个tree表,pid是其上级菜单的id。

要得到的查询结果Tree对象,这个对象是可以无限递归的
public class Tree {
String id;
String name;
List<Tree> child;
dao
@Mapper
public interface TreeDao {
@ResultMap("tree")
@Select("SELECT p1.id,p1.name,p2.id id2,p2.name name2,p3.id id3,p3.name name3 "
+ "FROM tree p1,tree p2,tree p3 WHERE p1.id=p2.pid AND p2.id=p3.pid")
public List findTree();

这个SQL在数据库中的查询结果是这样的,可以发现前四个字段是一样的,而且都是冗余数据,如果用java注解的关联查询是不会这样的


@ResultMap("tree"):映射结果集id是tree,前面说了,这个映射要在xml中配置
application.properties文件中添加配置
#指定xml映射文件的路径
mybatis.mapper-locations=classpath:hello/mapper/*

hello.mapper.TreeMapper.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="hello.dao.TreeDao">
<!-- 结果集类型 -->
<resultMap id="tree" type="hello.pojo.Tree">
<!-- 映射字段 -->
<result column="id" property="id" />
<result column="name" property="name" />
<!-- 嵌套第二张表 -->
<collection property="child" ofType="hello.pojo.Tree" >
<id column="id2" property="id" />
<result column="name2" property="name" />
<!-- 嵌套第三张表 -->
<collection property="child" ofType="hello.pojo.Tree" >
<id column="id3" property="id" />
<result column="name3" property="name" />
</collection>
</collection>
</resultMap>
</mapper>

这里只是配置一个嵌套映射,在dao方法中通过@ResultMap("tree")使用这个映射。最终查询结果会映射成一个Tree对象,通过spring mvc转换为json结果如下,在一些前端框架中,实现树形菜单就是需要用这种结构的JSON数据赋值

[
{
"id": "1",
"name": "一级树",
"child": [
{
"id": "11",
"name": "二级树-1",
"child": [
{
"id": "112",
"name": "三级树-1",
"child": null
},
{
"id": "113",
"name": "三级树-2",
"child": null
}
]
}
]
}
]

使用JAVA注解还是XML

XML执行一条SQL语句,并不是一定比JAVA注解执行多条SQL性能更优
一条SQL:关联的表越多,笛卡尔积越大,查询结果的冗余数据也越多
多条SQL:只需单表查询,如果做好索引查询效率会非常高,查询结果也没有冗余 。
在现实中,如果使用其中一种方式的性能较低,则可以偿试另一方式进行测试,同时还要考虑数据库优化策略

spring boot(9)-mybatis关联映射的更多相关文章

  1. Spring Boot (11) mybatis 关联映射

    一对多 查询category中的某一条数据,同时查询该分类下的所有Product. Category.java public class Category { private Integer id; ...

  2. 【spring boot】14.spring boot集成mybatis,注解方式OR映射文件方式AND pagehelper分页插件【Mybatis】pagehelper分页插件分页查询无效解决方法

    spring boot集成mybatis,集成使用mybatis拖沓了好久,今天终于可以补起来了. 本篇源码中,同时使用了Spring data JPA 和 Mybatis两种方式. 在使用的过程中一 ...

  3. Spring Boot整合Mybatis完成级联一对多CRUD操作

    在关系型数据库中,随处可见表之间的连接,对级联的表进行增删改查也是程序员必备的基础技能.关于Spring Boot整合Mybatis在之前已经详细写过,不熟悉的可以回顾Spring Boot整合Myb ...

  4. Spring Boot整合Mybatis并完成CRUD操作

    MyBatis 是一款优秀的持久层框架,被各大互联网公司使用,本文使用Spring Boot整合Mybatis,并完成CRUD操作. 为什么要使用Mybatis?我们需要掌握Mybatis吗? 说的官 ...

  5. 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 ...

  6. Spring Boot集成MyBatis开发Web项目

    1.Maven构建Spring Boot 创建Maven Web工程,引入spring-boot-starter-parent依赖 <project xmlns="http://mav ...

  7. 详解Spring Boot集成MyBatis的开发流程

    MyBatis是支持定制化SQL.存储过程以及高级映射的优秀的持久层框架,避免了几乎所有的JDBC代码和手动设置参数以及获取结果集. spring Boot是能支持快速创建Spring应用的Java框 ...

  8. spring boot + druid + mybatis + atomikos 多数据源配置 并支持分布式事务

    文章目录 一.综述 1.1 项目说明 1.2 项目结构 二.配置多数据源并支持分布式事务 2.1 导入基本依赖 2.2 在yml中配置多数据源信息 2.3 进行多数据源的配置 三.整合结果测试 3.1 ...

  9. Spring Boot 实战 —— MyBatis(注解版)使用方法

    原文链接: Spring Boot 实战 -- MyBatis(注解版)使用方法 简介 MyBatis 官网 是这么介绍它自己的: MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过 ...

随机推荐

  1. 基于flex的不定个数的按钮组

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  2. C++中class的类型转换重载

    注:本文测试实例使用的编译器版本为clang-703.0.29. 我们已经习惯了基本数据类型的显式或隐示转换,如: ; float f = (float)a;float c = a; 其实通过oper ...

  3. 09 - JavaSE之线程

    线程 线程的基本概念 线程是一个程序里面不同的执行路径. 进程与线程的区别 每个进程都有独立的代码和数据空间(进程上下文),进程间的切换开销大. 线程可以看作轻量级的进程,同一类线程共享代码和数据空间 ...

  4. C++中对象模型

    C++面向对象语言一大难点是继承,但又是不得不掌握的.简单的继承是很容易理解的,但是当涉及到多继承,设计到虚函数的继承,特别是涉及到虚继承时,问题就会变得复杂.下面的内容来自参考资料中的三篇文章.C+ ...

  5. java.lang.NoSuchMethodError: org.json.JSONArray.iterator()Ljava/util/Iterator 阿里云短信

    请尝试使用 <dependency> <groupId>com.aliyun</groupId> <artifactId>aliyun-java-sdk ...

  6. Linux 文件IO管理 - POSIX

    以下是对POSIX的简短解释: POSIX表示可移植操作系统接口(Portable Operating System Interface of UNIX,缩写为 POSIX ),POSIX标准定义了操 ...

  7. jar命令简单使用

    以windows10操作系统,JDK1.8为例: 打包主要是针对class文件以及依赖的jar包. 1.编写MANIFEST.MF文件(详细可以上网查一下MANIFEST.MF文件规则.) 此文件主要 ...

  8. [转]微信小程序之购物车功能

    本文转自:https://www.cnblogs.com/linxin/p/6834206.html 前言 以往的购物车,基本都是通过大量的 DOM 操作来实现.微信小程序其实跟 vue.js 的用法 ...

  9. 单击GridView进入编辑模式

    一直以来,Insus.NET在实现GridView编辑时,均是在每笔记录第一列或是最后一列放置编辑铵钮,点击编辑铵钮之后,进行编辑模式.本博文是使用另外方式,即是点击GridView记录行任一位置,进 ...

  10. UA 用户代理

    User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本.CPU 类型.浏览器及版本.浏览器渲染引擎.浏览器语言.浏览器插件等.被广泛用来标识 ...