众所周知,Mybatis Plus 封装的 mapper 不支持 join,如果需要支持就必须自己去实现。但是对于大部分的业务场景来说,都需要多表 join,要不然就没必要采用关系型数据库了。
直到前几天,偶然碰到了这么一款叫做mybatis-plus-join
的工具(后面就简称mpj
了),使用了一下,不得不说真香!彻底将我从xml地狱中解放了出来,终于可以以类似mybatis-plus
中QueryWrapper
的方式来进行联表查询了,话不多说,我们下面开始体验。
首先在项目中引入引入依赖坐标,因为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
项目中,像往常一样正常配置数据源连接信息就可以了。
implementation 'com.github.yulichang:mybatis-plus-join-boot-starter:1.4.4'
class test {
@Resource
private UserMapper userMapper;
void testJoin() {
//和Mybatis plus一致,MPJLambdaWrapper的泛型必须是主表的泛型,并且要用主表的Mapper来调用
MPJLambdaWrapper wrapper = new MPJLambdaWrapper()
.selectAll(UserDO.class)//查询user表全部字段
.select(UserAddressDO::getTel)//查询user_address tel 字段
.selectAs(UserAddressDO::getAddress, UserDTO::getUserAddress)//别名 t.address AS userAddress
.select(AreaDO::getProvince, AreaDO::getCity)
.leftJoin(UserAddressDO.class, UserAddressDO::getUserId, UserDO::getId)
.leftJoin(AreaDO.class, AreaDO::getId, UserAddressDO::getAreaId)
.eq(UserDO::getId, 1)
.like(UserAddressDO::getTel, "1")
.gt(UserDO::getId, 5);
//连表查询 返回自定义ResultType
List list = userMapper.selectJoinList(UserDTO.class, wrapper);
//分页查询 (需要启用 mybatis plus 分页插件)
Page listPage = userMapper.selectJoinPage(new Page<>(2, 10), UserDTO.class, wrapper);
}
}
对应sql
SELECT
t.id, t.name, t.sex, t.head_img,
t1.tel, t1.address AS userAddress,
t2.province, t2.city
FROM
user t
LEFT JOIN user_address t1 ON t1.user_id = t.id
LEFT JOIN area t2 ON t2.id = t1.area_id
WHERE (
t.id = ?
AND t1.tel LIKE ?
AND t.id > ?)
说明:
MPJLambdaWrapper 还有很多其他的功能
https://gitee.com/best_handsome/mybatis-plus-join/wikis/selectFunc()?sort_id=4082479
https://gitee.com/best_handsome/mybatis-plus-join/wikis/leftJoin?sort_id=3496671
等效于ResultMap
MPJLambdaWrapper其他功能
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
也可以这样进行分页。
经过简单的测试,个人感觉mpj
这款工具在联表查询方面还是比较实用的,能更应对项目中不是非常复杂的场景下的sql查询,大大提高我们的生产效率。当然,在项目的issues
中也能看到当前版本中也仍然存在一些问题,希望在后续版本迭代中能继续完善。
关注我,后续更新更多好用的工具,效率天花板