对于一对一,一对多,多对一,多对多的关联查询,Mybatis-Plus 在处理时,需要编写关联查询方法及配置resultMap,并且书写SQL。

为了简化这种操作,可以注解来简化。

Mybatis-Plus-Relation  ( mprelation ) : mybatis-plus 一对一、一对多、多对一、多对多的自动关联查询,注解方式。

mprelation源码地址  :

     github:     https://github.com/dreamyoung/mprelation.git

     gitee:        https://gitee.com/dreamyoung/mprelation.git

mprelation_demo 地址  :

    github:      https://github.com/dreamyoung/mprelation_demo.git 

    gitee:        https://gitee.com/dreamyoung/mprelation_demo.git

POM引用 :

  1. <dependency>
  2. <groupId>com.github.dreamyoung</groupId>
  3. <artifactId>mprelation</artifactId>
  4. <version>0.0.3.1-RELEASE</version>
  5. </dependency>

注解工具使用优缺点:

优点:

使用简单,通过在实体类上添加@OneToOne / @OneToMany@ManyToOne@ManyToMany  等注解即可。

1对1、1对多、多对1、多对多映射时,可以不再写SQL及XML配置文件,免去配置冗长的<resultMap>的麻烦。

Service层及Mapper层不需要再添加 getLinkById 、 selectLinkById   之类的方法来关联映射

重写过的ServiceImpl各种内置的查询方法都自动关联查询,非内置方法可以调用autoMapper相关方法进行自动或手动关联

解决关联处理的1+n问题

缺点:

目前只针对SqlSession/Mappe形式有效(ActiveRecord形式暂未涉及修改,也没有测试)

非事务下, 1个连接(1个SqlSession)只执行一条SQL,而自动获取每个关联属性的sql都会创建1~2个SqlSession(并执行1~2条SQL)。

★ 可通过配置事务,让所有关联属性都使用同一个SqlSession(此时非延迟加载的关联属性无论有多少都可以同在一个事务一个SqlSession中执行,而每个延迟加载的关联属性,在自动触发时还会创建一次SqlSession,但可以配置为非自动触发---即实体类上标注@AutoLazy(false)或没有标注该注解(默认),之后通过initialize方法在事务范围内的一个SqlSession中同时加载多个延迟加载的属性。)

使用注意点:

ServiceImpl内置的业务查询,配置事务管理,减少SqlSession的创建。

实体上可用注解@AutoLazy(true/false)来标注是否自动触发延迟加载

★  true或无值的话,则获取延迟的关联属性时自动关联。

★  false或者不标注该注解的话,需要手动通过initialize()方法对延迟的关联属性进行获取,否则不会自动关联获取,此时关联为空

如果可以,不使用延迟加载(延迟加载的使用是在SqlSession关闭后执行的,需要重新创建SqlSession)。

如果确实需要延迟加载,可使用ServiceImpl   AutoMapper 相关的initialize方法一次性加载所有需要的被延迟的属性(只需要创建额外的一个SqlSession,毕竟SqlSession之前已经关闭)

注解使用:

一对多(多对一) :

Company实体类中配置:

  1. @Data
  2. public class Company {
  3. @TableId(value = "company_id")
  4. private Long id;
  5. private String name;
  6.  
  7. //一对多
  8. @TableField(exist = false)
  9. @OneToMany //一对多默认为延迟加载,即@Lazy/@Lazy(true)/或此时不标注
  10. @JoinColumn(name="company_id",referencedColumnName = "company_id") //@TableId与一方相关属性中@TableField名称保持一致时@JoinColumn可省略
  11. private Set<Man> employees;
  12. }

Man实体类中配置:

  1. @Data
  2. public class Man {
  3.  
  4. @TableId(value = "man_id")
  5. private Long id;
  6. private String name;
  7.  
  8. //多对一
  9. @TableField("company_id")
  10. private Long companyId;
  11.  
  12. @TableField(exist = false)
  13. @ManyToOne //多对一默认为立即加载,即@Lazy(false)或此时不标注
  14. @JoinColumn(name = "company_id", referencedColumnName = "company_id") //相关的@TableField与多方的@TableId名称一致时@JoinColumn可省略
  15. private Company company;
  16. }

一对多(多对一)表结构:  company: (compnay_id,   name)           man: (man_id,    name,   company_id)

一对一:

Woman实体类配置:

  1. @Data
  2. public class Woman {
  3. @TableId(value = "woman_id")
  4. private Long id;
  5. private String name;

  6. //一对一
    @TableField("lao_gong_id")
  7. private Long laoGongId;
  8.  
  9. @TableField(exist = false)
  10. @OneToOne //一对一默认为立即加载,即@Lazy(false)或此时不标注
  11. @JoinColumn(name = "lao_gong_id", referencedColumnName = "man_id")
    private Man laoGong;
  12. }

Man实体类配置:

  1. @Data
  2. public class Man {
  3. @TableId(value = "man_id")
  4. private Long id;
  5. private String name;
  6.  
  7. //一对一
    @TableField("lao_po_id")
  8. private Long laoPoId;
  9.  
  10. @TableField(exist = false)
  11. @OneToOne
  12. @JoinColumn(name = "lao_po_id", referencedColumnName = "woman_id")
  13. private Woman laoPo;
  14. }

一对一表结构:(实际可以减少一方)  woman: (woman_id,  name,   lao_gong_id)           man: (man_id,   name,   lao_po_id)

多对多:

Course实体类配置:

  1. @Data
  2. public class Course {
  3. @TableId(value = "course_id")
  4. private Long id;
  5. private String name;
  6.  
  7. //多对多
  8. @TableField(exist = false)
  9. @ManyToMany //多对多默认为延迟加载,即@Lazy(true)或此时不标注
  10. @JoinTable(targetMapper = StudentCourseMapper.class) //第三方命名为StudentCourseMapper或CourseStudentMapper时@JoinTable注解一般可省略
  11. @JoinColumn(name = "course_id", referencedColumnName = "course_id")
  12. @InverseJoinColumn(name = "child_id", referencedColumnName = "student_id")
  13. private List<Child> students;
  14. }

Child实体类配置:

  1. @Data
  2. public class Child {
  3. @TableId("child_id")
  4. private Long id;
  5. private String name;
  6.  
  7. //多对多
  8. @TableField(exist = false)
  9. @ManyToMany
  10. @JoinTable(targetMapper=StudentCourseMapper.class)
  11. @JoinColumn(name = "child_id", referencedColumnName = "student_id")
  12. @InverseJoinColumn(name = "course_id", referencedColumnName = "course_id")
    private List<Course> courses;
  13. }

StudenCourse中间类(多对多必须要有,如果命名为StudentCourse或CourseStudent,则上边的@JoinTable可省略):

  1. @Data
  2. public class StudentCourse {
  3. //可以有也可以无此ID
  4. private Long id;
  5.  
  6. @TableField("student_id")
  7. private Long studentId;
  8.  
  9. @TableField("course_id")
  10. private Long courseId;
  11. }

多对多表结构:course: (course_id,  name)          child: (child_id,   name)       student_course:(id,   student_id,    course_id)

mprelation 关联查询,使用过程:   

1.   POM中引入mprelation:

  1. <dependency>
  2. <groupId>com.github.dreamyoung</groupId>
  3. <artifactId>mprelation</artifactId>
  4. <version>0.0.3.1-RELEASE</version>
  5. </dependency>

配置 AutoMapper (只要是扫描被注解的实体类)

  1. @Configuration
  2. public class AutoMapperConfig {
  3. @Bean
  4. public AutoMapper autoMapper() {
  5. return new AutoMapper(new String[] { "demo.entity","demo.bean" }); //配置实体类所在目录(可多个,暂时不支持通过符*号配置)
  6. }
  7. }

2.   在实体类中配置注解(更多的注解配置见上边注解部分,这里只列出其中一个)

  1. @Data
  1. @AutoLazy //对标注了@Lazy(true)的延迟关联属性,当进行获取时启动自动触发加载,否则(即标注为false或没有该注解),须手动触发加载(如initialize等方法)再进行获取。
  1. public class Man {
  1. @TableId(value = "man_id")
  2. private Long id;
  3. private String name;
  4. private Long laoPoId;
  5. @TableField(exist = false)
  6. @OneToOne
  7. @JoinColumn(name = "lao_po_id", referencedColumnName = "woman_id")
  8. private Woman laoPo;

  9. @TableField("company_id")
  10. private Long companyId;
  11. @TableField(exist = false)
  12. @ManyToOne
  13. @JoinColumn(name = "company_id", referencedColumnName = "company_id")private Company company;

  14. @TableField(exist = false)
  15. @OneToMany
  16. @JoinColumn(name = "man_id", referencedColumnName = "lao_han_id")
    private List<Child> waWa;

  1. @TableField(exist = false)
  2. @OneToMany
  3. @JoinColumn(name = "man_id", referencedColumnName = "man_id")
  4. @Lazy(false)
  5. private Set<Tel> tels;
  6. }

3.   在Service层、Mapper层的使用,见下面:

以下是基于Mybatis-Plus官方示例修改而来的测试程序:

通过继承工具类重写过的IService /  ServiceImpl   会自动执行关联映射, 无须再写gettLinkById之类的方法(可以使得各实现类没有任何方法):

mapper接口:

  1. public interface ManMapper extends BaseMapper<Man> {}

service接口:

  1. public interface IManService extends IService<Man> {} // IService为重写过的同名接口

Service实现:

  1. @Service
  2. public class ManServiceImpl extends ServiceImpl<ManMapper, Man> implements IManService {} // ServiceImpl为重写过的同名接口

测试调用:

  1. public class ServiceTest {
  2. @Autowired
  3. ManService manService;
  4.  
  5. @Test
  6. public void t_man_serviceImpl() {
  7. Man man = manService.getById(1); // 原Mybatis-Plus的ServiceImpl的各种查询,被重写过后,都可以自动关联,
    System.out.println(man);
  8. }
  9. }

结果输出:

  1. Man(
    id=1,
    name=程序猿小明,
    laoPoId=1,
    laoPo=Woman(id=1, name=程序猿小明老婆, laoGongId=1, laoGong=null, waWa=null),
    companyId=1,
    company=Company(id=1, name=百度, employees=null),
    waWa=[
    Child(id=1,name=xxx1,lao_han_id=null, laoHan=null, lao_ma_id=null, laoMa=null, courses=null),
    Child(id=2,name=xxxx2, lao_han_id=null, laoHan=null, lao_ma_id=null, laoMa=null, courses=null)
    ],
    tels=[
    Tel(id=1, tel=139xxxxxx, manId=1, laoHan=null),
    Tel(id=4, tel=159xxxxxx, manId=1, laoHan=null),
    Tel(id=2, tel=137xxxxxx, manId=1, laoHan=null)
    ]
    )

如需需要对其关联属性对象的关联属性进行自动加载,可以继续使用AutoMapper对象的mapperEntity、mapperEntityList、mapperEntitySet、mapperEntityPage来操作:

比如想获取(填充)waWas 的关联,则:

  1. List waWas=man.getWaWas();
  2. autoMapper.mapperEntityList(waWas);

AutoMapper类中的几个常用方法说明:

mapperEntity(entity)                                            可以对一个实体类,实现自动关联。

mapperEntityList(entity_list)                                可以对一个实体类List,实现自动关联。

mapperEntitySet(entity_set)                                可以对一个实体类Set,实现自动关联。

mapperEntityCollection(entity_list_or_set)          可以对一个实体类Set或List,实现自动关联。

mapperEntityPage(entity_page)                          可以对一个实体类Page,实现自动关联。

initialize(entity/entityList/entitySet/entityPage,    OneOrMoreLazyPropertyName ...)

可以对一个实体类/实体类List/实体类Set/实体类Page,在事务范围内,手动立即触发其各个被@Lazy(true)标注的关联属性。

该方法在重写过的ServiceImpl内也存在(供Controller层调用来加载延迟关联的属性)。

AutoMapper在重写过的ServiceImpl类中已经自动注入可用(名为autoMapper),其它情况也可以手动注入:

  1. public class MPRTest2 {
  2. @Autowired
  3. AutoMapper autoMapper;
  4.  
  5. @Resource
  6. private ManMapper manMapper;
  7.  
  8. @Test
  9. public void t_man() {
  10. Man man = manMapper.selectById(1L);
  11. autoMapper.mapperEntity(man);
  12. System.out.println(man);
  13. }
  14.  
  15. }

 最新版本POM:

  1. <dependency>
  2. <groupId>com.github.dreamyoung</groupId>
  3. <artifactId>mprelation</artifactId>
  4. <version>0.0.3.1-RELEASE</version>
  5. </dependency>

github:   https://github.com/dreamyoung/mprelation

  1.  

MyBatis-Plus不写任何resultMap和SQL执行一对一、一对多、多对多关联查询的更多相关文章

  1. MyBatis 一对多,多对一关联查询的时候Mapper的顺序

    要先写association,然后写collection:这是由DTD决定的: <resultMap ...> <association ...> </associati ...

  2. mybatis实战教程二:多对一关联查询(一对多)

    多对一关联查询 一.数据库关系.article表和user表示多对一的关系 CREATE TABLE `article` ( `id` ) NOT NULL AUTO_INCREMENT, `user ...

  3. mybatis多对多关联查询

    多对多关系 一个学生可以选多门课程,而一门课程可以由多个学生选择,这就是一个典型的多对多关联关系.所谓多对多关系,其实是由两个互反的一对多关系组成.即多对多关系都会通过一个中间表来建立,例如选课表.学 ...

  4. mybatis 14: 多对一关联查询

    业务背景 根据订单id查询订单的信息,以及该订单所属的客户的基本信息(不包括该客户自己的订单信息) 两张数据表 客户表 订单表 实体类 客户实体类:Customer private Integer i ...

  5. 精尽 MyBatis 源码分析 - SqlSession 会话与 SQL 执行入口

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  6. mybatis一对多关系的关联查询

    问题描述:实现两张表的关联查询 学生表: 班级表: 要实现学生管理信息中有所在班级的名称,即如下图所示 1.对应学生表的pojo类写全班级表中的字段(适用于要连接的表字段较少的情况) sql语句直接在 ...

  7. mybatis多对多关联查询——(十)

    1.需求 查询用户及用户购买商品信息. 2     sql语句 查询主表是:用户表 关联表:由于用户和商品没有直接关联,通过订单和订单明细进行关联,所以关联表: orders.orderdetail. ...

  8. mybatis实现多表一对一,一对多,多对多关联查询

    原文:https://blog.csdn.net/m0_37787069/article/details/79247321 1.一对一关键字:association作用:针对pojo对象属性的映射  ...

  9. mybatis 一对多和多对一关联查询

    首先  数据库量表之间字段关系(没有主外键) studentmajor表的id字段对应student表里major字段 两个实体类 package com.model; import java.uti ...

随机推荐

  1. android多框架实现短视频应用、3D手势旋转、banner控件、指南针、智能管家等应用源码

    Android精选源码 android智能管家app源码 Android高仿拼多多分类列表 Android百度地图实例详解之仿摩拜单车APP RecyclerView的LayoutManager搭建流 ...

  2. LeetCode No.76,77,78

    No.76 MinWindow 最小覆盖子串 题目 给你一个字符串 S.一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串. 示例 输入: S = "ADOBECODEB ...

  3. deeplearning.ai 构建机器学习项目 Week 1 机器学习策略 I

    这门课是讲一些分析机器学习问题的方法,如何更快速高效的优化机器学习系统,以及NG自己的工程经验和教训. 1. 正交化(Othogonalization) 设计机器学习系统时需要面对一个问题是:可以尝试 ...

  4. Serializable 接口(序列化)

    目录 Serializable 接口(序列化) 前言 用途 如何实现 异常 serialVersionUID transient关键字 Serializable 接口(序列化) 前言 查看API文档时 ...

  5. Docker 安装 CentOS

    Docker 安装 CentOS CentOS(Community Enterprise Operating System)是 Linux 发行版之一,它是来自于 Red Hat Enterprise ...

  6. JavaScript设计模式一:工厂模式和构造器模式

    转自:http://segmentfault.com/a/1190000002525792 什么是模式 前阵子准备期末考试,挺累也挺忙的,实在闲不得空来更新文章,今天和大家说说javascript中的 ...

  7. 吴裕雄--天生自然HTML学习笔记:HTML 属性

    属性是 HTML 元素提供的附加信息. HTML 属性 HTML 元素可以设置属性 属性可以在元素中添加附加信息 属性一般描述于开始标签 属性总是以名称/值对的形式出现,比如:name="v ...

  8. 吴裕雄--天生自然 R语言开发学习:图形初阶

    # ----------------------------------------------------# # R in Action (2nd ed): Chapter 3 # # Gettin ...

  9. from PIL import image报错

    python中import PIL可以,但是from PIL import Image就报错? ’‘ 大家在安装pillow的时候,可能会安装成功,但是当运行from pIL import image ...

  10. springboot ——oracle.jdbc.driver.OracleDriver

    网上很多案例讲是oracle的驱动包没有导入进去,我之前尝试下图示方式导入解决该问题: 但是在后期调试的时候,发现会影响后续oracle数据源连接驱动的问题,导致不能查询,因此想,另辟途径,解决这个问 ...