项目地址: 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. vue实现输入框的模糊查询(节流函数的应用场景)

    上一篇讲到了javascript的节流函数和防抖函数,那么我们在实际场合中该如何运用呢? 首先,我们来理解一下:节流函数首先是节流,就是节约流量.内存的损耗,旨在提升性能,在高频率频发的事件中才会用到 ...

  2. 将excel中某列数据中,含有指定字符串的记录取出,并生成用这个字符串命名的txt文件

    Python 一大重要的功能,就是可处理大量数据,那分不开的即是使用Excel表格了,这里我做下学习之后的总结,望对我,及广大同仁们是一个帮助Python处理Excel数据需要用到2个库:xlwt 和 ...

  3. HTML(一)简介,元素

    HTML简介 html实例: <!DOCTYPE html> 菜鸟教程 我的第一个标题 我的第一个段落 实例解析: <!DOCTYPE html> 声明为 HTML5 文档,不 ...

  4. F-maximum clique 1_2019牛客暑期多校训练营(第五场)

    题意 给出n个不同的数字\(a_i\),求出最大的子集,使得子集内任意两个数在二进制下至少有两位不同. 题解 先对任意两个二进制位只有一个不同的两个数连边,那么问题就转化成找出最多的点集,任意两点没有 ...

  5. 【转载】Why Learning to Code is So Damn Hard By Erik Trautman

    原文网址:https://www.thinkful.com/blog/why-learning-to-code-is-so-damn-hard/ 在罗老师的<算法竞赛 入门到进阶>总看到了 ...

  6. hdu 2767 Proving Equivalences(tarjan缩点)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2767 题意:问最少加多少边可以让所有点都相互连通. 题解:如果强连通分量就1个直接输出0,否者输出入度 ...

  7. 基于注解的读取excel的工具包

    easyexcel-wraper easyexcel-wraper是什么? 一个方便读取excel内容,且可以使用注解进行内容验证的包装工具 easyexcel-wraper有哪些功能? 在easye ...

  8. 【LeetCode】347-前K个高频元素

    题目描述 给定一个非空的整数数组,返回其中出现频率前 k 高的元素. 示例 1: 输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2] 示例 2: 输入: nums = ...

  9. 弄懂goroutine调度原理

    goroutine简介 golang语言作者Rob Pike说,"Goroutine是一个与其他goroutines 并发运行在同一地址空间的Go函数或方法.一个运行的程序由一个或更多个go ...

  10. js获取一个月的天数

    在使用其他语言获取每月天数的时候,一般都是存储到一个数组中进行获取,但是如果是二月份的话就需要首先判断是否闰年,再确定是28还是29了. js可以通过Date对象很方便的获取到每月的天数,在初始化Da ...