项目地址: mybatis-dynamic-query

前言

在 2.0 完成对 tk.mapper 集成,为何 mybatis-dynamic-query 选择 tk.mapper 集成, 再 3.0 进一步对查询进行优化,当然这里可能会对比 mybatis-plus, 我觉得有对比大家才能选择自己合适的。

更新内容

  1. 添加 DynamicQueryBuilder 步骤化生成 DynamicQuery 语句
  2. 优化 DynamicQuery 添加,移除筛选和排序

DynamicQueryBuilder 引入

这个在 3.0 引入,目的是为了让大家写查询的时候真的像写 sql (严格遵循 sql 查询顺序),最后通过 build 方法来 build 一个 DynamicQuery, 根据经验来看 DynamicQueryBuilder 适合筛选条件已知的情况下。

public List<ProductsDO> getProductListByBuilder() {
// select product_name, list_price, category
// where (list_price > 1 and list_price < 10) and description is not null or id = 1
// order by id desc, list_price asc
DynamicQuery<ProductsDO> query = DynamicQueryBuilder.create(ProductsDO.class)
.select(ProductsDO::getProductName, ProductsDO::getListPrice, ProductsDO::getCategory)
.where(ProductsDO::getListPrice, greaterThan(BigDecimal.ONE),
and(ProductsDO::getListPrice, lessThan(BigDecimal.TEN)))
.and(ProductsDO::getDescription, notEqual(null))
.or(ProductsDO::getId, isEqual(1))
.orderBy(ProductsDO::getId, desc())
.thenBy(ProductsDO::getListPrice, asc())
.build();
return productMapper.selectByDynamicQuery(query);
}

DynamicQuery 筛选排序优化

DynamicQuery 的很多方法名被改了,和 DynamicQueryBuilder 基本保持一致,这样大家在使用的时候比较方便,从下面的例子大家可以看到可以在任何位置添加筛选或者排序并且和 if 判断语句结合

@Test
public void testGetProductListByQuery() {
BigDecimal startPrice = BigDecimal.valueOf(1.1);
BigDecimal endPrice = BigDecimal.valueOf(10.1);
DynamicQuery<ProductsDO> query = DynamicQuery.createQuery(ProductsDO.class)
.select(ProductsDO::getProductName, ProductsDO::getListPrice, ProductsDO::getCategory);
// 根据参数添加筛选条件,这里就是我们看看开始价,结束价有没有,如果有才会放到一个组里面,
if (Objects.nonNull(startPrice) || Objects.nonNull(endPrice)) {
FilterGroupDescriptor<ProductsDO> priceFilterGroup = new FilterGroupDescriptor<>();
if (Objects.nonNull(startPrice)) {
priceFilterGroup.and(ProductsDO::getListPrice, greaterThan(startPrice));
}
if (Objects.nonNull(endPrice)) {
priceFilterGroup.and(ProductsDO::getListPrice, lessThan(endPrice));
}
}
query.and(ProductsDO::getDescription, notEqual(null))
.or(ProductsDO::getId, isEqual(1))
.orderBy(ProductsDO::getId, desc())
.orderBy(ProductsDO::getListPrice, asc());
List<ProductsDO> result = productMapper.selectByDynamicQuery(query);
Assert.assertFalse(result.isEmpty());
}

enable 字段

大家看到上面例子, 有 if 判断条件会断开一个查询,这个在阅读的时候非常不方便,有了 enable 可以设置这个筛选是否生效,这样我们写代码的可读性高了

@Test
public void testGetProductListByQuery2() {
BigDecimal startPrice = BigDecimal.valueOf(1.1);
BigDecimal endPrice = BigDecimal.valueOf(10.1);
// 根据参数添加筛选条件,这里就是我们看看开始价,结束价有没有,如果有才会放到一个组里面,
DynamicQuery<ProductsDO> query = DynamicQuery.createQuery(ProductsDO.class)
.select(ProductsDO::getProductName, ProductsDO::getListPrice, ProductsDO::getCategory)
.and(group -> group
.and(ProductsDO::getListPrice, greaterThan(startPrice), Objects.nonNull(startPrice))
.and(ProductsDO::getListPrice, lessThan(endPrice), Objects.nonNull(endPrice)))
.and(ProductsDO::getDescription, notEqual(null))
.or(ProductsDO::getId, isEqual(1))
.orderBy(ProductsDO::getId, desc())
.orderBy(ProductsDO::getListPrice, asc());
List<ProductsDO> result = productMapper.selectByDynamicQuery(query);
Assert.assertFalse(result.isEmpty());
}

对比

开始我是不知道 mybatis-plus 博客园动态查询第一帖 的不然的话,可能我就直接用了哈哈~,既然自己做了一个也和标杆对比一下吧,但还是期望大家选择自己合适的吧,这里我只对比 mybatis-plus 查询功能。

举例

复杂条件查询

基本和动态查询在写法上基本表现一致,不过新版的动态插叙加上了 enable 字段以后读起来会好一些

@Test
public void testGetProductListByPlus() {
BigDecimal startPrice = BigDecimal.valueOf(1.1);
BigDecimal endPrice = BigDecimal.valueOf(10.1);
LambdaQueryWrapper<ProductsDO> queryWrapper = new QueryWrapper<ProductsDO>().lambda()
.select(ProductsDO::getListPrice, ProductsDO::getProductName, ProductsDO::getCategory);
if (Objects.nonNull(startPrice) && Objects.nonNull(endPrice)) {
// 没有找到如何将连个price 筛选放到一个组里面
queryWrapper.and(obj -> obj.gt(ProductsDO::getListPrice, startPrice)
.lt(ProductsDO::getListPrice, endPrice));
} else if (Objects.nonNull(startPrice)) {
queryWrapper.gt(ProductsDO::getListPrice, startPrice);
} else if (Objects.nonNull(endPrice)) {
queryWrapper.lt(ProductsDO::getListPrice, startPrice);
}
queryWrapper.ne(ProductsDO::getDescription, null)
.or(obj -> obj.eq(ProductsDO::getId, 1))
.orderByDesc(ProductsDO::getId)
.orderByAsc(ProductsDO::getListPrice);
List<ProductsDO> result = productPlusMapper.selectList(queryWrapper);
Assert.assertFalse(result.isEmpty());
}

灵活性

mybatis-plus 是非常灵活的, api 特别多, 比如 queryWrapper 可以直接接上操作符比如 eq,gt, lt 也可以接 and, or, 但是动态查询对于筛选只能接 and / or 操作符必须在里面, 我个人喜欢统一性,这其实就是仁者见仁智者见智了。

安全性

类型检查

可以说这个就是动态查询的优势了,设计之初就是怎么样让用户写出不会错的代码,所以所有的筛选值都是强类型,比如说字段 Price 是一个 BigDecimal, 如果写 Integer 就会报错,但是 mybatis-plus 就不会报错。

@Test
public void testGetProductListByQuery2() {
BigDecimal startPrice = BigDecimal.valueOf(1.1);
BigDecimal endPrice = BigDecimal.valueOf(10.1);
Integer integerStartPrice = 1;
DynamicQuery<ProductsDO> query = DynamicQuery.createQuery(ProductsDO.class)
.select(ProductsDO::getProductName, ProductsDO::getListPrice, ProductsDO::getCategory)
.and(group -> group
// 这段代码 会包错,因为integerStartPrice 不是BigDecimal 类型的
.and(ProductsDO::getListPrice, greaterThan(integerStartPrice), Objects.nonNull(startPrice))
.and(ProductsDO::getListPrice, lessThan(endPrice), Objects.nonNull(endPrice)))
.and(ProductsDO::getDescription, notEqual(null))
.or(ProductsDO::getId, isEqual(1))
.orderBy(ProductsDO::getId, desc())
.orderBy(ProductsDO::getListPrice, asc());
List<ProductsDO> result = productMapper.selectByDynamicQuery(query);
Assert.assertFalse(result.isEmpty());
}

链式调用

这个动态查询和 mybatis-plus 都是支持的,不一样的是,动态查询不会随意接后面的方法,是做过验证的,但是 mybatis-plus 比较灵活,把这个安全性检查交给用户了。

比如

@Test
public void testGetProductListByPlus() {
BigDecimal startPrice = BigDecimal.valueOf(1.1);
BigDecimal endPrice = BigDecimal.valueOf(10.1);
LambdaQueryWrapper<ProductsDO> queryWrapper = new QueryWrapper<ProductsDO>().lambda()
.select(ProductsDO::getListPrice, ProductsDO::getProductName, ProductsDO::getCategory);
if (Objects.nonNull(startPrice) && Objects.nonNull(endPrice)) {
// 这里我随意在筛选后面添加了一个排序, 编译的时候没有错,执行的时候会报错
queryWrapper.and(obj -> obj.gt(ProductsDO::getListPrice, startPrice)
.lt(ProductsDO::getListPrice, endPrice).orderByAsc(ProductsDO::getListPrice));
} else if (Objects.nonNull(startPrice)) {
queryWrapper.gt(ProductsDO::getListPrice, startPrice);
} else if (Objects.nonNull(endPrice)) {
queryWrapper.lt(ProductsDO::getListPrice, startPrice);
}
queryWrapper.ne(ProductsDO::getDescription, null)
.or(obj -> obj.eq(ProductsDO::getId, 1))
.orderByDesc(ProductsDO::getId)
.orderByAsc(ProductsDO::getListPrice);
List<ProductsDO> result = productPlusMapper.selectList(queryWrapper);
Assert.assertFalse(result.isEmpty());
}

小结

主要给大家看了一下 3.0 对查询的改动,主要也是给大家多一个选择, 稍微对比了一下 mybatis-plus, 自我感觉在查询写法上面有优势,但是 mybatis-plus 是功能非常多,大而全的一整套解决方案,文档非常完善,这也是动态查询不具备的,所以大家选择自己合适的。

mybatis-dynamic-query 3.0 更新的更多相关文章

  1. Mybatis Dynamic Query 2.0.2

    项目地址:https://github.com/wz2cool/mybatis-dynamic-query 文档地址:https://wz2cool.gitbooks.io/mybatis-dynam ...

  2. Mybatis Dynamic Query 1.0.2版本

    项目地址:https://github.com/wz2cool/mybatis-dynamic-query 文档地址:https://wz2cool.gitbooks.io/mybatis-dynam ...

  3. Mybatis Dynamic Query 2.0 入门

    简介 2.0 昨天打包好了,主要是整合了tk.mybatis.mapper 到项目中去,所以和1.x比起来主要多了一个通用mapper.因为作者主要是使用springboot 这里讲一下Springb ...

  4. Mybatis Dynamic Query 框架整合

    项目地址:https://github.com/wz2cool/mybatis-dynamic-query 文档地址:https://wz2cool.gitbooks.io/mybatis-dynam ...

  5. Mybatis Dynamic Query 更新

    文章目录 1. 简介 2. 准备工作 3. 开始更新 3.1. update 3.2. update Null 4. 结束 5. 关注@我 项目地址:https://github.com/wz2coo ...

  6. Mybatis Dynamic Query 简单筛选

    在框架中,筛选描述类有两种(FilterDescriptor, FilterGroupDescriptor),这里我们主要举例来说明FilterDescriptor用法. FilterDescript ...

  7. [Liferay6.2]Liferay Dynamic Query API示例

    介绍 Liferay提供了几种方法定义复杂的查询用来检索数据库中的数据. 通常情况下,在每个service Entity中,通过定义一些'finder'方法,可以便捷地满足基本的数据查询操作. 但是, ...

  8. Mybatis分页插件2.0版本号公布

    项目地址:http://git.oschina.net/free/Mybatis_PageHelper 软件介绍:http://www.oschina.net/p/mybatis_pagehelper ...

  9. mybatis学习之路----批量更新数据两种方法效率对比

    原文:https://blog.csdn.net/xu1916659422/article/details/77971696/ 上节探讨了批量新增数据,这节探讨批量更新数据两种写法的效率问题. 实现方 ...

  10. 【mybatis】mybatis中批量插入 批量更新 batch 进行insert 和 update,或者切割LIst进行批量操作

    ================================================================== 分别展示 mybatis 批量新增  和 批量更新   的操作: ...

随机推荐

  1. CocosBuilder 学习笔记(3) AnimationManager 与 ccbi 文件解析

    [CocosBuilder]学习笔记目录 1. 相关的类 先介绍和AnimationManager相关的几个类: CCBSequence 时间线.有成员duration(时间线时间,默认10秒).na ...

  2. 深度解密Go语言之 scheduler

    目录 前置知识 os scheduler 线程切换 函数调用过程分析 goroutine 是怎么工作的 什么是 goroutine goroutine 和 thread 的区别 M:N 模型 什么是 ...

  3. 使用ansible对思科交换机备份

    先决条件 - 了解ansible基本操作 - 了解网络设备相关操作 - 了解linux相关操作 安装 安装EPEL yum install https://dl.fedoraproject.org/p ...

  4. “adobe premiere中画面和声音不同步” 解决方法

    一.背景 之前在segmentfault上过直播课,直播课有录制回播功能:尝试听了下直播课,发现视频太长了,感觉听起来非常花费学员的时间,在回放中其实有一些直播课里面的内容并不需要,所以准备剪辑一下, ...

  5. 从Linux服务器下载上传文件

    首先要确定好哪两种的连接:Linux常用的有centors和unbantu两种版本,PC端Mac和Windows 如果在两个Linux之间传输,或Linux和Mac之间传输可以使用scp命令,类似于s ...

  6. 牛客20347 SDOI2011计算器(bsgs

    https://ac.nowcoder.com/acm/problem/20347 这篇是为了补bsgs(北上广深算法). 题意: 1.给定y,z,p,计算Y^Z Mod P 的值:  2.给定y,z ...

  7. 楼房重建 HYSBZ - 2957

    楼房重建 HYSBZ - 2957 第一次写分块, 写了之后觉得真的是暴力的一比. 题解:先讲n分成 sqrt(n)块,记得补上末尾的, 然后就是对于每一次更新操作, 都重新的讲这个块里面的有效楼放入 ...

  8. Codeforces 416D Population Size

    Population Size 题意: 一共n个数, 每个-1都可以变成一个正数, 现在要求最少数目的等差子序列,并且在这个子序列必须要连着截取一段,不能分开截取. 样例1: 8 6 4 2 1 4 ...

  9. Light It Up CF1000B 思维

    Light It Up time limit per test 1 second memory limit per test 256 megabytes input standard input ou ...

  10. csapp:第八章 异常控制流ECF

    第八章 异常控制流ECF 8.1 异常 Exception graph LR E[异常Exception]-->E2[中断:异步异常] E-->E3[同步异常] E3-->陷阱 E3 ...