项目地址:https://github.com/wz2cool/mybatis-dynamic-query

文档地址:https://wz2cool.gitbooks.io/mybatis-dynamic-query-zh-cn/content/

杂谈

不知道有多少人在用MDQ(Mybatis Dynamic Query),反正我一直是在我们公司自己项目里用的,总之是不会坑大家的啊。还有毕竟作者也是入java坑不久,欢迎java大神前来指导。

面对质疑

当然有人一开始真心接受不了我这套,无非就几点:

  • 问题1:来个新人还要学习MDQ,只理解Mybatis上手要容易的多。

    反驳:MDQ没有产生一套新的东西,而是基于Mybatis的一个扩展,理解MDQ对Mybatis更加有帮助。
  • 问题2:我直接在mybatis里面写sql感觉写起来比较快。

    反驳:一开始你是写起来快,最开始你只写几个查询,随着业务扩展,你要写的筛选和排序会越来越多,更可怕的事,你全部写在xml中,想想你以后要维护一个弱类型的东西...
  • 问题3:你写的东西感觉不靠谱。

    反驳:大神写的同样有bug,好的代码需要反复重构,并且保持良好的单元测试,这个是不变的真理,有问题可以,大家讨论一下解决即可。

2.2 更新

更新了三点:

  1. 原来是有自定义筛选的,现在添加了自定义排序。
  2. 设计MDQ的目的就是为了可维护性,所以这次添加了获取查询列,即[tableName].[columnName] 这种形式。
  3. 链式调用,等下看例子就明白了。

查询列

这个查询列大家可能有点云里雾里,列就叫列,为什么叫查询列。其实MDQ工作的时候对数据库查询是[tableName].[columnName], 这样做有个好处就是当我们join表的时候,我们可以指定这个列是哪里来的,保证查询的正确性。

当然你这个拼接工作是由MDQ完成的,我们只需要在@Column 这个注解设计 tableOrAlias 和name 两个属性即可。当然为什么要这个查询列,我在下面的自定义排序中说明。

下面我们来看个例子,还是用我们经典的ProductView。

  1. public class ProductView {
  2. @Column(name = "product_id", table = "product")
  3. private Long productID;
  4. @Column(name = "product_name", table = "product")
  5. private String productName;
  6. @Column(name = "price", table = "product")
  7. private BigDecimal price;
  8. @Column(name = "category_id", table = "category")
  9. private Long categoryID;
  10. @Column(name = "category_name", table = "category")
  11. private String categoryName;
  12. @Column(name = "description", table = "category")
  13. private String description;
  14. ...
  15. }
  1. @Test
  2. public void testGetQueryColumn() throws Exception {
  3. String productIdColumn = MybatisQueryProvider.getQueryColumn(
  4. ProductView.class, productView -> productView.getProductID());
  5. // 这里我们就可以看到期望的输出结果就是 [tableName].[columnName]
  6. assertEquals("product.product_id", productIdColumn);
  7. }

自定义筛选

其实和自定义筛选类似,就是我们可以hardcode 一小段我们自己的sql(虽然觉得不是很好)。

当然下面例子也会使用到查询列。

现在我们有个需求,我们需要把ProductID是2的产品放到第一个,常规的升序降序都不能满足我们,我们该怎么办呢,恩 我们重新自定义一下排序权重即可。

  1. @Test
  2. public void testCustomSort() throws Exception {
  3. String idQueryColumn = MybatisQueryProvider.getQueryColumn(ProductView.class, ProductView::getProductID);
  4. // NOTE: queryColumn cannot be parameter.
  5. // 这里注意:列不能当做参数,否则会报错,所以我们字符串拼接出来。
  6. String customSortExpression =
  7. String.format("CASE %s WHEN {0} THEN {1} ELSE product.product_id END DESC", idQueryColumn);
  8. CustomSortDescriptor id2TopSort = new CustomSortDescriptor();
  9. id2TopSort.setExpression(customSortExpression);
  10. // 当id是2的时候,我们权重直接给int 最大值
  11. id2TopSort.setParams(2, Integer.MAX_VALUE);
  12. Map<String, Object> queryParam =
  13. MybatisQueryProvider.createInstance(ProductView.class)
  14. .addSorts("orderExpression", id2TopSort)
  15. .toQueryParam();
  16. List<ProductView> productList = northwindDao.getProductViewsByDynamic(queryParam);
  17. assertEquals(Long.valueOf(2), productList.get(0).getProductID());
  18. }

我们看一下输出结果,2的产品排序到了最上面去了。

  1. ==> Preparing: SELECT * FROM product LEFT JOIN category ON product.category_id = category.category_id ORDER BY CASE product.product_id WHEN ? THEN ? ELSE product.product_id END DESC
  2. ==> Parameters: 2(Integer), 2147483647(Integer)
  3. <== Columns: PRODUCT_ID, CATEGORY_ID, PRODUCT_NAME, PRICE, CATEGORY_ID, CATEGORY_NAME, DESCRIPTION
  4. <== Row: 2, 2, Northwind Traders Syrup, 7.5000, 2, Condiments, test
  5. <== Row: 4, 3, Northwind Traders Olive Oil, 16.5000, 3, Oil, test
  6. <== Row: 3, 2, Northwind Traders Cajun Seasoning, 16.5000, 2, Condiments, test
  7. <== Row: 1, 1, Northwind Traders Chai, 18.0000, 1, Beverages, test
  8. <== Total: 4

链式调用

这个应该是我在哪本java 文章看过,反正感觉不错啊。

以前的调用我们非要组织一个DynamicQuery类,然后调用一个静态方法生成一个参数Map,有了链式调用我们写代码就方便了很多。

看我们一个步骤,创建帮助类-》添加筛选-》添加排序-》转化成参数。

  1. @Test
  2. public void testMultiTablesFilter() throws Exception {
  3. FilterDescriptor priceFilter1 =
  4. new FilterDescriptor(ProductView.class, ProductView::getPrice,
  5. FilterOperator.GREATER_THAN_OR_EQUAL, 6);
  6. FilterDescriptor priceFilter2 =
  7. new FilterDescriptor(ProductView.class, ProductView::getPrice,
  8. FilterOperator.LESS_THAN, 10);
  9. FilterDescriptor categoryNameFilter =
  10. new FilterDescriptor(ProductView.class, ProductView::getCategoryName,
  11. FilterOperator.START_WITH, "Co");
  12. SortDescriptor idDescSort =
  13. new SortDescriptor(ProductView.class, ProductView::getProductID, SortDirection.DESC);
  14. Map<String, Object> params =
  15. // NOTE: we recommend you to set "columnsExpressionPlaceholder"
  16. // in case of duplicated column name in two tables.
  17. // 这里你也可以不给列的站位,但是推荐使用,防止两个表有重复的名字
  18. MybatisQueryProvider
  19. .createInstance(ProductView.class, "columnsExpression")
  20. .addFilters("whereExpression",
  21. priceFilter1, priceFilter2, categoryNameFilter)
  22. .addSorts("orderExpression", idDescSort)
  23. .toQueryParam();
  24. List<ProductView> result = northwindDao.getProductViewsByDynamic(params);
  25. assertEquals(true, result.size() > 0);
  26. }

看一下输出结果

  1. ==> Preparing: SELECT product.product_id AS product_id, product.price AS price, category.description AS description, category.category_name AS category_name, product.product_name AS product_name, category.category_id AS category_id FROM product LEFT JOIN category ON product.category_id = category.category_id WHERE (product.price >= ? AND product.price < ? AND category.category_name LIKE ?) ORDER BY product.product_id DESC
  2. ==> Parameters: 6(Integer), 10(Integer), Co%(String)
  3. <== Columns: PRODUCT_ID, PRICE, DESCRIPTION, CATEGORY_NAME, PRODUCT_NAME, CATEGORY_ID
  4. <== Row: 2, 7.5000, test, Condiments, Northwind Traders Syrup, 2
  5. <== Total: 1

结束

利用十一的时间更行了2.0.2,欢迎大家节后回来使用。

关注我 ##

最后大家可以关注我和 Mybatis-Dynamic-query项目 _

Follow @wz2cool Star Fork

文章整合

Mybatis Dynamic Query 简单筛选

Mybatis Dynamic Query 组筛选

Mybatis Dynamic Query 排序

Mybatis Dynamic Query 筛选+排序

Mybatis Dynamic Query 插入

Mybatis Dynamic Query 更新

Mybatis Dynamic Query 删除

Mybatis Dynamic Query 属性表达式

Mybatis Dynamic Query join视图

Mybatis Dynamic Query 2.0 入门

Mybatis Dynamic Query 2.0.2的更多相关文章

  1. Mybatis Dynamic Query 1.0.2版本

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

  2. Mybatis Dynamic Query 2.0 入门

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

  3. Mybatis Dynamic Query 框架整合

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

  4. Mybatis Dynamic Query 简单筛选

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

  5. Mybatis Dynamic Query 更新

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

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

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

  7. Error:dijit.tree.TreeStoreModel:root query returned 0 items

    1.错误描述 error loading root:                                            Tree.js(第341行) Error:dijit.tre ...

  8. org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.mybatis.spring.mapper.MapperScannerConfigurer#0'

    七月 05, 2018 10:26:54 上午 org.apache.tomcat.util.digester.SetPropertiesRule begin警告: [SetPropertiesRul ...

  9. query.setFirstResult(0),query.setMaxResults(4)

    query.setFirstResult(0),query.setMaxResults(1);相当于MySQL中的limit 0, 1; String hql = "FROM Forum f ...

随机推荐

  1. 5.分析内核中断运行过程,以及中断3大结构体:irq_desc、irq_chip、irqaction

    本节目标:    分析在linux中的中断是如何运行的,以及中断3大结构体:irq_desc.irq_chip.irqaction 在裸板程序中(参考stmdb和ldmia详解): 1.按键按下, 2 ...

  2. Project 1 :创建链表与显示链表

    目标:创建一个链表,并将链表输出.结构体中包括学号与分数.链表以输入学号为0作为结束.输出模版为 No.学号 Score:分数 输入样例: 10101 98 10102 97 10103 100 10 ...

  3. 转:【Java并发编程】之二十三:并发新特性—信号量Semaphore(含代码)

    载请注明出处:http://blog.csdn.net/ns_code/article/details/17524153 在操作系统中,信号量是个很重要的概念,它在控制进程间的协作方面有着非常重要的作 ...

  4. [我所理解的REST] 3.基于网络应用的架构

    上篇中解释到什么是架构风格和应该以怎样的视角来理解REST(Web的架构风格).本篇来介绍一组自洽的术语,用它来描述和解释软件架构:以及列举下对于基于网络的应用来说,哪些点是需要我们重点关注的. 1 ...

  5. 201521123099 《Java程序设计》第6周学习总结

    1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰,内容覆盖 ...

  6. 201521123101 《Java程序设计》第4周学习总结

    1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 1.2 使用常规方法总结其他上课内容. 理解类的继承的概念,明白父与子之间关系的 2. 书面作业 1.注释的应用,使用类的注释与方法 ...

  7. 201521123059 《Java程序设计》第十二周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student对象(属性:int id, String name,int age,doubl ...

  8. 201521123122 《java程序设计》第十周学习总结

    ## 201521123122 <java程序设计>第十周实验总结 ## 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次P ...

  9. 201521123089 《Java程序设计》第10周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 1.finally 题目4-21.1 截图你的提交结果(出现 ...

  10. thinkphp介绍及访问方式

    ThinkPHP框架 1.解压到www目录下,里面有一个index文件是入口文件,通过修改里面的APP_PATH进入不同的应用 2.ThinkPHP文件夹是核心文件夹,里面东西不要修改,可以查看,比如 ...