mybatis-plus-join MPJ连表查询 这样写太香了!

news2024/11/27 23:43:16

mybatis-plus作为mybatis的增强工具,它的出现极大的简化了开发中的数据库操作,但是长久以来,它的联表查询能力一直被大家所诟病。一旦遇到left joinright join的左右连接,你还是得老老实实的打开xml文件,手写上一大段的sql语句。

直到前几天,偶然碰到了这么一款叫做mybatis-plus-join的工具(后面就简称mpj了),使用了一下,不得不说真香!彻底将我从xml地狱中解放了出来,终于可以以类似mybatis-plusQueryWrapper的方式来进行联表查询了,话不多说,我们下面开始体验。

引入依赖

首先在项目中引入引入依赖坐标,因为mpj中依赖较高版本mybatis-plus中的一些api,所以项目建议直接使用高版本。

<dependency>
    <groupId>com.github.yulichang</groupId>
    <artifactId>mybatis-plus-join</artifactId>
    <version>1.2.4</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.1</version>
</dependency>

引入相关依赖后,在springboot项目中,像往常一样正常配置数据源连接信息就可以了。

数据准备

因为要实现联表查询,所以我们先来建几张表进行测试。

订单表:

在这里插入图片描述
用户表,包含用户姓名:

在这里插入图片描述
商品表,包含商品名称和单价:
在这里插入图片描述
在订单表中,通过用户id和商品id与其他两张表进行关联。

修改Mapper

以往在使用myatis-plus的时候,我们的Mapper层接口都是直接继承的BaseMapper,使用mpj后需要对其进行修改,改为继承MPJBaseMapper接口。

@Mapper
public interface OrderMapper extends MPJBaseMapper<Order> {
}

对其余两个表的Mapper接口也进行相同的改造。此外,我们的service也可以选择继承MPJBaseServiceserviceImpl选择继承MPJBaseServiceImpl,这两者为非必须继承。

查询

Mapper接口改造完成后,我们把它注入到Service中,虽然说我们要完成3张表的联表查询,但是以Order作为主表的话,那么只注入这一个对应的OrderMapper就可以,非常简单。

@Service
@AllArgsConstructor
public class OrderServiceImpl implements OrderService {
    private final OrderMapper orderMapper;
}

MPJLambdaWrapper

接下来,我们体验一下再也不用写sql的联表查询:

public void getOrder() {
    List<OrderDto> list = orderMapper.selectJoinList(OrderDto.class,
     new MPJLambdaWrapper<Order>()
      .selectAll(Order.class)
      .select(Product::getUnitPrice)
      .selectAs(User::getName,OrderDto::getUserName)
      .selectAs(Product::getName,OrderDto::getProductName)
      .leftJoin(User.class, User::getId, Order::getUserId)
      .leftJoin(Product.class, Product::getId, Order::getProductId)
      .eq(Order::getStatus,3));

    list.forEach(System.out::println);
}

不看代码,我们先调用接口来看一下执行结果:
在这里插入图片描述
可以看到,成功查询出了关联表中的信息,下面我们一点点介绍上面代码的语义。

首先,调用mapperselectJoinList()方法,进行关联查询,返回多条结果。后面的第一个参数OrderDto.class代表接收返回查询结果的类,作用和我们之前在xml中写的resultType类似。

这个类可以直接继承实体,再添加上需要在关联查询中返回的列即可:

@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class OrderDto extends Order {
    String userName;
    String productName;
    Double unitPrice;
}

接下来的MPJLambdaWrapper就是构建查询条件的核心了,看一下我们在上面用到的几个方法:

  • selectAll():查询指定实体类的全部字段

  • select():查询指定的字段,支持可变长参数同时查询多个字段,但是在同一个select中只能查询相同表的字段,所以如果查询多张表的字段需要分开写

  • selectAs():字段别名查询,用于数据库字段与接收结果的dto中属性名称不一致时转换

  • leftJoin():左连接,其中第一个参数是参与联表的表对应的实体类,第二个参数是这张表联表的ON字段,第三个参数是参与联表的ON的另一个实体类属性

除此之外,还可以正常调用mybatis-plus中的各种原生方法,文档中还提到,默认主表别名是t,其他的表别名以先后调用的顺序使用t1、t2、t3以此类推。

我们用插件读取日志转化为可读的sql语句,可以看到两条左连接条件都被正确地添加到了sql中:
在这里插入图片描述

MPJQueryWrapper

mybatis-plus非常类似,除了LamdaWrapper外还提供了普通QueryWrapper的写法,改造上面的代码:

public void getOrderSimple() {
    List<OrderDto> list = orderMapper.selectJoinList(OrderDto.class,
     new MPJQueryWrapper<Order>()
      .selectAll(Order.class)
      .select("t2.unit_price","t2.name as product_name")
      .select("t1.name as user_name")
      .leftJoin("t_user t1 on t1.id = t.user_id")
      .leftJoin("t_product t2 on t2.id = t.product_id")
      .eq("t.status", "3")
    );

    list.forEach(System.out::println);
}

运行结果与之前完全相同,需要注意的是,这样写时在引用表名时不要使用数据库中的原表名,主表默认使用t,其他表使用join语句中我们为它起的别名,如果使用原表名在运行中会出现报错。

并且,在MPJQueryWrapper中,可以更灵活的支持子查询操作,如果业务比较复杂,那么使用这种方式也是不错的选择。

分页查询

mpj中也能很好的支持列表查询中的分页功能,首先我们要在项目中加入分页拦截器:

@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
    MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
    interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
    return interceptor;
}

接下来改造上面的代码,调用**selectJoinPage()**方法:

public void page() {
    IPage<OrderDto> orderPage = orderMapper.selectJoinPage(
      new Page<OrderDto>(2,10),
      OrderDto.class,
      new MPJLambdaWrapper<Order>()
        .selectAll(Order.class)
        .select(Product::getUnitPrice)
        .selectAs(User::getName, OrderDto::getUserName)
        .selectAs(Product::getName, OrderDto::getProductName)
        .leftJoin(User.class, User::getId, Order::getUserId)
        .leftJoin(Product.class, Product::getId, Order::getProductId)
        .orderByAsc(Order::getId));

    orderPage.getRecords().forEach(System.out::println);
}

注意在这里需要添加一个分页参数的Page对象,我们再执行上面的代码,并对日志进行解析,查看sql语句:
在这里插入图片描述
可以看到底层通过添加limit进行了分页,同理,MPJQueryWrapper也可以这样进行分页。

最后

经过简单的测试,个人感觉mpj这款工具在联表查询方面还是比较实用的,能更应对项目中不是非常复杂的场景下的sql查询,大大提高我们的生产效率。当然,在项目的issues中也能看到当前版本中也仍然存在一些问题,希望在后续版本迭代中能继续完善。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/423454.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【unity实战】用对象池设计制作Dash冲锋残影的效果

什么是对象池? 在Unity中,对象池是一种重复使用游戏对象的技术。使用对象池的好处是可以减少游戏对象的创建和销毁,从而提高游戏的性能。如果不使用对象池,每次需要创建游戏对象时,都需要调用Unity的Instantiate函数,这会导致内存分配和垃圾回收的开销。而使用对象池,可…

李宏毅 深度学习【持续更新】

目录pytorch快速入门csdn快速入门OS包PIL包Opencv包Dataset类Tensorboard的使用torchvision.transforms 的使用torchvision中数据集的使用DataLoader的使用(torch.utils.data)神经网络的搭建nn.Module深度学习 李宏毅Chatgpt1 研究方向2 Chatgpt学习的步骤3 Fine tune vs. Prom…

【Linux内网穿透】使用SFTP工具快速实现内网穿透

文章目录内网穿透简介1. 查看地址2.局域网测试连接3.创建tcp隧道3.1. 安装cpolar4.远程访问5.固定TCP地址内网穿透简介 是一种通过公网将内网服务暴露出来的技术&#xff0c;可以使得内网服务可以被外网访问。以下是内网穿透的一些应用&#xff1a; 远程控制&#xff1a;通过内…

九【springboot】

Springboot一 Spring Boot是什么二 SpringBoot的特点1.独立运行的spring项目三 配置开发环境四 配置开发环境五 创建 Spring Boot 项目1.在 IntelliJ IDEA 欢迎页面左侧选择 Project &#xff0c;然后在右侧选择 New Project&#xff0c;如下图2.在新建工程界面左侧&#xff0c…

深入理解PyTorch中的train()、eval()和no_grad()

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️&#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

【数据结构】栈的实现

&#x1f61b;作者&#xff1a;日出等日落 &#x1f4d8; 专栏&#xff1a;数据结构 &#x1f339; 如果说&#xff0c;读书是在奠定人生的基石&#xff0c;在梳理人生的羽毛&#xff0c;那么&#xff0c;实践&#xff0c;就是在构建人生的厅堂&#xff0c;历练人生的翅膀。是不…

阿里P7晒工资条,看完好扎心了……

前几天&#xff0c;有位老粉私信我&#xff0c;说看到某95后学弟晒出阿里P7的工资单&#xff0c;他是真酸了…想狠补下技术&#xff0c;努力冲一把大厂。 为了帮到他&#xff0c;也为了大家能在最短的时间内做面试复习&#xff0c;我把软件测试面试系列都汇总在这一篇文章了。 …

自然语言处理: 知识图谱的十年

动动发财的小手&#xff0c;点个赞吧&#xff01; NLP 中结合结构化和非结构化知识的研究概况 自 2012 年谷歌推出知识图谱 (KG) 以来&#xff0c;知识图谱 (KGs) 在学术界和工业界都引起了广泛关注 (Singhal, 2012)。作为实体之间语义关系的表示&#xff0c;知识图谱已被证明与…

ECharts 横向柱状图自动滚动

核心代码 const seriesList [120, 200, 150, 80, 70, 110, 130, 120, 200, 150, 120, 200]; const xAxisList [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; const dataZoomEndValue 6; // 数据窗口范围的结束数值(一次性展示几个) dataZoom: [{show: false, // 是否显示滑动…

Java面向对象高级【类加载器】

目录 Java程序是怎样被运行的 类加载器的作用 加载类文件 链接类 定位类 类加载器间的委派 实现类的隔离 类加载器的类型 启动类加载器&#xff08;Bootstrap Class Loader&#xff09; 扩展类加载器&#xff08;Extension Class Loader&#xff09; 应用程序类加载器…

数据结构和算法学习记录——二叉树的非递归遍历(中序遍历、先序遍历、后序遍历)

目录 中序遍历 代码实现 思路图解 先序遍历 代码实现 后序遍历 思路图解 二叉树的非递归遍历运用到堆栈 中序遍历 循环的思路是 遇到一个节点&#xff0c;就把它压栈&#xff0c;并去遍历它的左子树。当左子树遍历结束之后&#xff0c;从栈顶弹出这个节点并访问…

MybatisPlus主键策略

Mybatis默认主键策略是TableId(type IdType.ASSIGN_ID) 这是默认策略雪花算法 此时主键类型可以是String 数据表字段类型可以是bigint int varchar 无需数据表主键自增 TableId(type IdType.ASSIGN_AUTO) 是主键自增策略:该策略为跟随数据库表的主键递增策略&…

大数据挖掘建模平台产品功能特点

大数据挖掘建模平台是面向大数据挖掘教学实训的工具。在“泰迪杯”数据挖掘挑战赛中大多学生都有使用到该工具&#xff0c;平台采用可视化操作方式&#xff0c;通过丰富内置算法&#xff0c;帮助用户快速、一站式的进行数据分析及挖掘建模。可应用于处理海量数据、高复杂性的数…

C语言判断素数的实现及数学原理

本篇博客会讲解如何使用C语言来判断一个整数是不是素数。 实现方法 如何判断一个数是不是素数呢&#xff1f;如果这个数只能被1或者它自己整除&#xff0c;那么它就是一个素数。 如何写代码来判断呢&#xff1f;假设要判断一个数num是不是素数&#xff0c;就让2~(num-1)的数…

LeetCode037之解数独(相关话题:回溯法)

题目描述 编写一个程序,通过填充空格来解决数独问题。 数独的解法需 遵循如下规则: 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)数独部分空格内已填入了数字,空白格用 . 表示…

Nginx入门和使用

Nginx入门 基础 https://blog.csdn.net/weixin_40792878/article/details/83316519 快速入门 Nginx 是一个高性能的 HTTP 和反向代理服务器&#xff0c;特点是占有内存少&#xff0c;并发能力强&#xff1b; 代理&#xff1a;用于隐藏客户端或者目标服务器&#xff0c;是客…

通过案例来了解响应式开发(HTML,CSS)的视频控件

目录 前言 一、视频控件的使用方法 1.语法 二、部分属性 二、案例举例 三、播放效果 前言 1.本文讲解的响应式开发技术&#xff08;HTML5CSS3Bootstrap&#xff09;的HTML5表单等功能方法的代码&#xff0c;这也是很多教材的一个典型案例&#xff1b; 2.本文将讲解涉及到…

腾讯轻联测试预览报错怎么办?

在腾讯轻联配置过程中&#xff0c;经常遇到测试预览失败的报错。首先我们整体介绍一下【测试预览】的作用。增加【测试预览】的节点的作用主要有两个&#xff1a; ● 第一个作用是为了保证我们应用连接能通畅&#xff0c;可以获取到数据&#xff0c;避免后续由于设置问题&…

IntelliJ IDEA安装及jsp开发环境搭建

一、前言 现在.net国内市场不怎么好&#xff0c;公司整个.net组技术转型&#xff0c;就个人来说还是更喜欢.net&#xff0c;毕竟不是什么公司都像微软一样财大气粗开发出VS这样的宇宙级IDE供开发者使用&#xff0c;双击sln即可打开项目&#xff0c;一直想吐槽为嘛java项目只能i…

Docker Registry 本地镜像发布到私有库

本地镜像发布到私有库流程 是什么1 官方Docker Hub地址&#xff1a;https://hub.docker.com/&#xff0c;中国大陆访问太慢了且准备被阿里云取代的趋势&#xff0c;不太主流。2 Dockerhub、阿里云这样的公共镜像仓库可能不太方便&#xff0c;涉及机密的公司不可能提供镜像给公…