MyBatis-Plus联表查询的短板,该如何解决呢
创始人
2024-05-31 21:06:21
0

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

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

1 引入依赖

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

com.github.yulichangmybatis-plus-join1.2.4

com.baomidoumybatis-plus-boot-starter3.5.1

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

2 数据准备

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

订单表:

用户表,包含用户姓名:

商品表,包含商品名称和单价:

在订单表中,通过用户id和商品id与其他两张表进行关联。

3 修改Mapper

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

@Mapper
public interface OrderMapper extends MPJBaseMapper {
}

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

4 查询

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

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

4.1使用MPJLambdaWrapper进行联表查询

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

public void getOrder() {List list = orderMapper.selectJoinList(OrderDto.class,new MPJLambdaWrapper().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);
}

不看代码,我们先调用接口来看一下执行结果:

可以看到,成功查询出了关联表中的信息,下面我们一点点介绍上面代码的语义。

首先,调用mapper的selectJoinList()方法,进行关联查询,返回多条结果。后面的第一个参数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中:

4.2 使用MPJQueryWrapper进行联表查询

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

public void getOrderSimple() {List list = orderMapper.selectJoinList(OrderDto.class,new MPJQueryWrapper().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中,可以更灵活的支持子查询操作,如果业务比较复杂,那么使用这种方式也是不错的选择。

5 分页查询

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

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

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

public void page() {IPage orderPage = orderMapper.selectJoinPage(new Page(2,10),OrderDto.class,new MPJLambdaWrapper().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也可以这样进行分页。

6 最后总结

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

相关内容

热门资讯

多城联动!辽宁消防“安全盛宴”...   5月8日,辽宁省消防救援总队以创意形式和贴心服务,在鞍山、抚顺、丹东、锦州、营口等地同步开展多元...
大美江湖,天下岳阳   千年巴陵,江湖旧梦;一座岳阳,四水归心。  当千年岳阳楼的飞檐在XR空间里再度挑起月色,当洞庭湖...
王帅红在全市开发区工作推进会上... 5月9日,全市开发区工作推进会召开。会议深入学习贯彻习近平总书记关于开发区工作的重要指示精神,认真贯...
林志玲深夜晒合照回忆与大S首次... 5月10日晚,林志玲晒合照,怀念第一次见到大S:第一次见到大S,是在一个冰淇淋店。当时还没有入行的我...
boc某行刚涨薪了? (转自:五道口江湖)近日,有多名山东、河北、河南地区boc行的网友分享,上个月涨薪了。其中山东地区的...
CPI环比由降转涨 部分工业行... 转自:衢州日报  4月份,全国居民消费价格指数(CPI)环比由上月下降0.4%转为上涨0.1%,扣除...
应急处置演练 转自:衢州日报  近日,柯城区衢化街道组织开展防汛防台应急处置演练。此次演练包括桌面推演和卫星电话、...
胡忠雄主持召开贵安新区党工委巡... 5月10日,省委常委、贵安新区党工委书记胡忠雄主持召开新区党工委巡视整改工作领导小组会议。他强调,要...
“夜游信安湖”入选省级精品航线 转自:衢州日报  本报讯 (通讯员 吴丽芬 戴晨涛) 近日,全省水路交旅融合品牌——“泛舟浙里”发布...
中原建业:1-4月合约销售35... 业绩快报5月9日,中原建业有限公司(股票代码:09982.HK,以下简称“中原建业”)发布2025年...
新华社评论员:守护历史记忆,共... 转自:北京日报客户端当地时间5月9日,俄罗斯莫斯科红场碧空澄澈、旗帜招展,纪念苏联伟大卫国战争胜利8...
2025年前4个月,我国货物贸... 海关总署日前发布数据显示,2025年前4个月,以人民币计,我国货物贸易进出口总值14.14万亿元,同...
南京鼓楼城管上门服务指导湖南路... 转自:扬子晚报扬子晚报网5月10日讯(通讯员 李亦军 记者 张可)近期,南京鼓楼城管大队湖管会中队联...
多出去玩能减少身体炎症 多接触大自然的人更健康与城市相比,自然环境中的景色、气味、声音更能促进身心健康。发表于美国《大脑行为...
头部投行美女转行瑜伽! (转自:五道口江湖)一名香港普拉提老师说:一年前的差不多这个時候我交还了Morgan Stanley...
中自科技携手天津大学、王成山院... 5月8日,在成都举办的“青城论道低碳能源共生发展”大会上,中自科技股份有限公司与天津大学、中国工程院...
鲁慕迅逝世,享年98岁 湖北省文联鲁慕迅同志治丧小组5月9日发布讣告,湖北省文联离休干部、省美术家协会原副主席、一级美术师鲁...
听·见|“被名言”借助网络泛滥... ——莫言说:“我不够成熟,不够圆滑,不够老练。没关系,我只不过是一个晚熟的人。”原来莫爷爷是我的同类...
曝光AL保险资管公司领导 (转自:五道口江湖)近日网传的一份文件,吐槽AL保险资管公司领导,对实习生不尊重,缺乏专业能力,人际...
成都蓉城客场4-0横扫梅州客家... 封面新闻记者 陈羽啸北京时间5月10日晚,2025赛季中超联赛第12轮在五华奥体中心展开争夺,成都蓉...