Mybatis-Plus中LambdaQueryWrapper与QueryWrapper的使用

文章目录

概要

在开发过程中,几乎每个需求都需要写一些最基础的crud操作,这在mapper和xml文件中会产生大量重复的代码,引入mybatis-plus可以解决最简单的crud以有效缓解,但大部分人在一些比较复杂的查询操作以及考虑sql优化的场景下依旧选择手写xml文件,但是mybatis-plus并不是无法解决这个问题。这篇文章就记录我对于mybatis-plus中的lambdaQueryWrapper和QueryWarpper的认识

Wrapper的基本使用

String username="chris";
        LambdaQueryWrapper<UmsAdmin> queryWrapper= Wrappers.<UmsAdmin>lambdaQuery().eq(UmsAdmin::getUsername,username);
        LambdaQueryWrapper<UmsAdmin> queryWrapper1 = new LambdaQueryWrapper<>();
        queryWrapper1.eq(UmsAdmin::getUsername,username);

        QueryWrapper<UmsAdmin> umsResourceQueryWrapper = new QueryWrapper<UmsAdmin>().eq("username",username);
        QueryWrapper<UmsAdmin> umsResourceQueryWrapper1 =Wrappers.<UmsAdmin>query().eq("username",username);

两种方式都是可以正常使用的,在lambdaQueryWrapper中使用new的形式会多一行代码,看个人喜好。两个参数中前者是表中的列名,后者是查询的条件

 lambdaQueryWrapper在使用eq,like等查询条件时。是会使用lambda表达式的方式,同时提示表中的列名,简化了开发,不需要去特意查看表中列名,以及有效降低了列名不正确导致的sql注入的风险。而QueryWrapper则需要提供正确的列名,同时编译的时候无法检查出错误

如果只是使用一个表的情况下,使用LambdaQueryWrapper会提高开发效率,如果是多个表的情况下,使用QueryWrapper可以实现更为复杂的sql语句。具体使用会在下文提及

QueryWrapper常用函数

QueryWrapper动态sql以及联表查询

动态sql

UmsAdmin是一个用户实体类,可以通过判断传入参数是否存在等逻辑进行sql的动态拼接

LambdaQueryWrapper<UmsAdmin> queryWrapper =Wrappers.lambdaQuery();
        queryWrapper.select(UmsAdmin::getUsername,UmsAdmin::getStatus,UmsAdmin::getEmail).eq(UmsAdm    in::getId,umsAdmin.getId());
        if(!umsAdmin.getStatus().equals(1)){
            queryWrapper.eq(UmsAdmin::getStatus,0);
        }
        if(umsAdmin.getUsername()!=null){
            queryWrapper.eq(UmsAdmin::getUsername,umsAdmin.getUsername());
        }
        return umsAdminMapper.selectList(queryWrapper);

QueryWrapper联表查询

QueryWrapper的联表查询如果想要使用join连接来优化查询速度的话需要引入mybatis-plus-join

maven项目引入如下依赖

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

 想使用leftjoin等连接查询需要在mapper文件中继承MPJBaseMapper<>,泛型需要使用查询的主表


public interface UmsResourceDao extends MPJBaseMapper<UmsResource> {

}

service代码如下

MPJLambdaWrapper<UmsResource> wrapper = JoinWrappers.lambda(UmsResource.class);

        wrapper.selectAll(UmsResource.class)
                .leftJoin(UmsRoleResourceRelation.class,UmsRoleResourceRelation::getResourceId,UmsResource::getId)
                .leftJoin(UmsAdminRoleRelation.class,UmsAdminRoleRelation::getRoleId,UmsRoleResourceRelation::getRoleId)
                .eq(UmsAdminRoleRelation::getAdminId,umsAdmin.getId());

对应sql:

select *//此处字段用*代替全部字段

from UmsResource t1 
leftjoin UmsRoleResourceRelation t2 on t1.id=t2.resource_id
leftjoin UmsAdminRoleRelation t3 on t3.role_id=t2.role_id
where t3.admin_id=${id}

 UmsResource是用户所拥有权限资源路径表,连接了角色资源关系表RoleResourceRelation,连接了用户角色关系表UmsAdminRoleRelation,最后的eq是在UmsAdminRoleRelation表中查询与传入参数相同id的用户所对应的角色。这三张表中,数据量最小的是UmsAdminRoleRelation,这一点与接下来的sql优化有关系。

需要注意的是,leftjoin中第一个lambda表达式一定是连表的字段,与第二个lambda表达式的字段不能互换。

若需要多字段比较连表,则可以

.leftJoin(UserAddressDO.class, on -> on
        .eq(UserAddressDO::getUserId,UserDO::getId)
        .eq(UserAddressDO::getId,UserDO::getId))

 leftjoin中每一个表或者字段都可以自由设置别名,条件构造器中例如eq,则在字段前加入一个字符串参数代表别名,而leftjoin中则在.class后加入字符串参数代表别名

更多mybatis-plus-join的使用方法,包括子查询,union等用法请移步到官方文档中查看

MyBatis-Plus-Join (yulichang.github.io)

sql性能优化

关于连表查询,我能想到的就是sql中使用数据量小的表来连接数据量大的表,以减少索引扫描循环的次数,以及想使用or连接条件时,需要前后字段都存在索引;不能让索引有范围查找;使用函数运算(该问题可在mysql8版本后使用函数索引优化),否则会出现索引失效问题。而此文章就用我的代码来试验一下使用小表驱动大表的优化效果,依旧是上文的查询

MPJLambdaWrapper<UmsAdminRoleRelation> wrapper1 = JoinWrappers.lambda(UmsAdminRoleRelation.class);

        wrapper1.leftJoin(UmsRoleResourceRelation.class,UmsRoleResourceRelation::getRoleId,UmsAdminRoleRelation::getRoleId)
                .leftJoin(UmsResource.class,UmsResource::getId,UmsRoleResourceRelation::getResourceId)
                .selectAll(UmsResource.class)
                .eq(UmsAdminRoleRelation::getAdminId,umsAdmin.getId());

对应sql如下:

 

SELECT t2.id,t2.create_time,t2.name,t2.url,t2.description,t2.category_id
FROM ums_admin_role_relation t
    LEFT JOIN ums_role_resource_relation t1 ON (t1.role_id = t.role_id)
    LEFT JOIN ums_resource t2 ON (t2.id = t1.resource_id)
WHERE (t.admin_id = ${id})

 使用explain分析执行计划可以看到两者的执行计划

优化前

 优化后

 记录两种sql循环1000次后的执行时间

看出有明显的优化

小结

mybatis-plus及其增强件mybatis-plus-join确实是可以实现大部分sql语句,包括一些复杂sql的实现,但是个人认为如果需要修改维护的sql,写在xml语句中的可读性会更强一些。比如在sql优化中,在xml可以直接拿到最终于数据库执行的sql去explain查看执行计划,而mybatis-plus-join则需要跑一次得到其执行的sql。而一些不怎么可能会去修改的复杂sql则可以用其在service中解决,以保证xml文件中保留的都是一些可能需要优化的sql语句

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值