数量:1

刘芳

三、认识“实例查询”

1、概念定义:

上面例子中,是这样创建“实例”的:Example ex = Example.of(customer, matcher);我们看到,Example对象,由customer和matcher共同创建,为讲解方便,我们先来明确一些定义。

A、实体对象:在持久化框架中与Table对应的域对象,一个对象代表数据库表中的一条记录,如上例中Customer对象。在构建查询条件时,一个实体对象代表的是查询条件中的“数值”部分。如:要查询姓“刘”的客户,实体对象只能存储条件值“刘”。

B、匹配器:ExampleMatcher对象,它是匹配“实体对象”的,表示了如何使用“实体对象”中的“值”进行查询,它代表的是“查询方式”,解释了如何去查的问题。如:要查询姓“刘”的客户,即姓名以“刘”开头的客户,该对象就表示了“以某某开头的”这个查询方式,如上例中:withMatcher("name", GenericPropertyMatchers.startsWith())

C、实例:即Example对象,代表的是完整的查询条件。由实体对象(查询条件值)和匹配器(查询方式)共同创建。

再来理解“实例查询”,顾名思义,就是通过一个例子来查询。要查询的是Customer对象,查询条件也是一个Customer对象,通过一个现有的客户对象作为例子,查询和这个例子相匹配的对象。

2、特点及约束(局限性):

1、支持动态查询。即支持查询条件个数不固定的情况,如:客户列表中有多个过滤条件,用户使用时在“地址”查询框中输入了值,就需要按地址进行过滤,如果没有输入值,就忽略这个过滤条件。对应的实现是,在构建查询条件Customer对象时,将address属性值置具体的条件值或置为null。

2、不支持过滤条件分组。即不支持过滤条件用 or(或) 来连接,所有的过滤查件,都是简单一层的用 and(并且) 连接。

3、仅支持字符串的开始/包含/结束/正则表达式匹配 和 其他属性类型的精确匹配。查询时,对一个要进行匹配的属性(如:姓名 name),只能传入一个过滤条件值,如以Customer为例,要查询姓“刘”的客户,“刘”这个条件值就存储在表示条件对象的Customer对象的name属性中,针对于“姓名”的过滤也只有这么一个存储过滤值的位置,没办法同时传入两个过滤值。正是由于这个限制,有些查询是没办法支持的,例如要查询某个时间段内添加的客户,对应的属性是 addTime,需要传入“开始时间”和“结束时间”两个条件值,而这种查询方式没有存两个值的位置,所以就没办法完成这样的查询。

四、重点理解ExampleMatcher

1、需要考虑的因素

查询条件的表示,有两部分,一是条件值,二是查询方式。条件值用实体对象(如Customer对象)来存储,相对简单,当页面传入过滤条件值时,存入相对应的属性中,没入传入时,属性保持默认值。查询方式是用匹配器ExampleMatcher来表示,情况相对复杂些,需要考虑的因素有:

(1)Null值的处理。当某个条件值为Null,是应当忽略这个过滤条件呢,还是应当去匹配数据库表中该字段值是Null的记录?

(2)基本类型的处理。如客户Customer对象中的年龄age是int型的,当页面不传入条件值时,它默认是0,是有值的,那是否参与查询呢?

(3)忽略某些属性值。一个实体对象,有许多个属性,是否每个属性都参与过滤?是否可以忽略某些属性?

(4)不同的过滤方式。同样是作为String值,可能“姓名”希望精确匹配,“地址”希望模糊匹配,如何做到?

(5)大小写匹配。字符串匹配时,有时可能希望忽略大小写,有时则不忽略,如何做到?

2、五个配置项

围绕上面一系列情况,ExampleMatcher中定义了5项配置来解决这些问题。

public class ExampleMatcher {

NullHandler nullHandler; //Null值处理方式

StringMatcher defaultStringMatcher; //默认字符串匹配方式

boolean defaultIgnoreCase; //默认大小写忽略方式

PropertySpecifiers propertySpecifiers; //各属性特定查询方式

Set ignoredPaths; //忽略属性列表

......

}

(1)nullHandler:Null值处理方式,枚举类型,有2个可选值,INCLUDE(包括),IGNORE(忽略)。标识作为条件的实体对象中,一个属性值(条件值)为Null是,是否参与过滤。当该选项值是INCLUDE时,表示仍参与过滤,会匹配数据库表中该字段值是Null的记录;若为IGNORE值,表示不参与过滤。

(2)defaultStringMatcher:默认字符串匹配方式,枚举类型,有6个可选值,DEFAULT(默认,效果同EXACT),EXACT(相等),STARTING(开始匹配),ENDING(结束匹配),CONTAINING(包含,模糊匹配),REGEX(正则表达式)。该配置对所有字符串属性过滤有效,除非该属性在 propertySpecifiers 中单独定义自己的匹配方式。

(3)defaultIgnoreCase:默认大小写忽略方式,布尔型,当值为false时,即不忽略,大小不相等。该配置对所有字符串属性过滤有效,除非该属性在 propertySpecifiers 中单独定义自己的忽略大小写方式。

(4)propertySpecifiers:各属性特定查询方式,描述了各个属性单独定义的查询方式,每个查询方式中包含4个元素:属性名、字符串匹配方式、大小写忽略方式、属性转换器。如果属性未单独定义查询方式,或单独查询方式中,某个元素未定义(如:字符串匹配方式),则采用 ExampleMatcher 中定义的默认值,即上面介绍的 defaultStringMatcher 和 defaultIgnoreCase 的值。

(5)ignoredPaths:忽略属性列表,忽略的属性不参与查询过滤。

3、操作方法

在ExampleMatcher中定义了一系列方式,用于设置这5项设置值,所有的设置方法均返回 ExampleMatcher 对象,所以支持链式编程配置。

(1)创建一个默认的 ExampleMatcher 对象。

定义:

public static ExampleMatcher matching()

默认配置如下:

A、nullHandler:IGNORE。Null值处理方式:忽略

B、defaultStringMatcher:DEFAULT。默认字符串匹配方式:默认(相等)

C、defaultIgnoreCase:false。默认大小写忽略方式:不忽略

D、propertySpecifiers:空。各属性特定查询方式,空。

E、ignoredPaths:空列表。忽略属性列表,空列表。

(2)改变Null值处理方式。

定义:

public ExampleMatcher withNullHandler(NullHandler nullHandler)

public ExampleMatcher withIncludeNullValues()

public ExampleMatcher withIgnoreNullValues()

产生效果:

改变配置项nullHandler,分别设为:指定值、INCLUDE(包括)、IGNORE(忽略)。

(3)改变默认字符串匹配方式。

定义:

public ExampleMatcher withStringMatcher(StringMatcher defaultStringMatcher)

产生效果:

改变配置项defaultStringMatcher,设为指定值。

(4)改变默认大小写忽略方式。

定义:

public ExampleMatcher withIgnoreCase()

public ExampleMatcher withIgnoreCase(boolean defaultIgnoreCase)

产生效果:

改变配置项defaultIgnoreCase,分别设为:true,指定值。

(5)向“忽略属性列表”中添加属性。

定义:

public ExampleMatcher withIgnorePaths(String... ignoredPaths)

产生效果:

改变配置项ignoredPaths,向列表中添加一个或多个属性。

(6)配置属性特定查询方式

一个属性的特定查询方式,包含了3个信息:字符串匹配方式、大小写忽略方式、属性转换器,存储在 propertySpecifiers 中,操作时用 GenericPropertyMatcher 类来传递配置信息。有4个方法来改变配置,这4个方法操作时,内部均采用增量改变的方式,即如果没有为属性定义“特定查询方式”,则会定义一个,并根据传进来的“非空信息”进行配置,如果已经定义有,则会根据传进来的“非空信息”进行更新。如果一个“特定查询方式”中的“字符串匹配方式、大小写忽略方式”没有设置值,查询时则采用ExampleMatcher中的默认配置。

A、自定义类的方式。

定义:

public ExampleMatcher withMatcher(String propertyPath, MatcherConfigurer matcherConfigurer)

产生效果:

向 propertySpecifiers 中增加或更新属性“特定查询方式”的配置。

参数说明:

propertyPath:要配置特定查询的属性名。

matcherConfigurer:自定义类对象。自定义类需要实现MatcherConfigurer接口,在接口的 configureMatcher() 实现方法中指定相关配置。

B、直接传入通用属性查询对象方式。

定义:

public ExampleMatcher withMatcher(String propertyPath, GenericPropertyMatcher genericPropertyMatcher)

产生效果:

向 propertySpecifiers 中增加或更新属性“特定查询方式”的配置。

参数说明:

propertyPath:要配置特定查询的属性名。

genericPropertyMatcher:直接传入一个通用查询对象。 ExampleMatcher.GenericPropertyMatchers工具类中提供了常用对象创建的静态方法,所有方法均返回 GenericPropertyMatcher 对象,所以支持链式编程配置。

另外:GenericPropertyMatcher 类本身也提供了诸多方法,用于改变相关配置项。

C、改变的大小写忽略方式

定义:

public ExampleMatcher withIgnoreCase(String... propertyPaths)

产生效果:

向 propertySpecifiers 中增加或更新属性“特定查询方式”中的“大小写忽略方式”配置。。

D、设置属性转换器

定义:

public ExampleMatcher withTransformer(String propertyPath, PropertyValueTransformer propertyValueTransformer)

产生效果:

向 propertySpecifiers 中增加或更新属性“特定查询方式”中的“属性转换器”配置。

五、常用情况说明

1、关于基本数据类型。

实体对象中,避免使用基本数据类型,采用包装器类型。如果已经采用了基本类型,

而这个属性查询时不需要进行过滤,则把它添加到忽略列表(ignoredPaths)中。

2、Null值处理方式。

默认值是 IGNORE(忽略),即当条件值为null时,则忽略此过滤条件,一般业务也是采用这种方式就可满足。当需要查询数据库表中属性为null的记录时,可将值设为INCLUDE,这时,对于不需要参与查询的属性,都必须添加到忽略列表(ignoredPaths)中,否则会出现查不到数据的情况。

3、默认配置、特殊配置。

默认创建匹配器时,字符串采用的是精确匹配、不忽略大小写,可以通过操作方法改变这种默认匹配,以满足大多数查询条件的需要,如将“字符串匹配方式”改为CONTAINING(包含,模糊匹配),这是比较常用的情况。对于个别属性需要特定的查询方式,可以通过配置“属性特定查询方式”来满足要求。

4、非字符串属性

如约束中所谈,非字符串属性均采用精确匹配,即等于。

5、忽略大小写的问题。

忽略大小的生效与否,是依赖于数据库的。例如 MySql 数据库中,默认创建表结构时,字段是已经忽略大小写的,所以这个配置与否,都是忽略的。如果业务需要严格区分大小写,可以改变数据库表结构属性来实现,具体可百度。

六、常用查询示例

以“快速入门”中的实体对象和模拟数据为例,列一些常用查询,方便开发时参考。

1、无匹配器的情况

要求:查询地址是“河南省郑州市”,且重点关注的客户。

说明:对于默认匹配器满足条件时,则不需要创建匹配器。

//创建查询条件数据对象

Customer customer = new Customer();

customer.setAddress("河南省郑州市");

customer.setFocus(true);

//创建实例

Example ex = Example.of(customer);

//查询

List ls = dao.findAll(ex);

//输出结果

System.out.println("数量:"+ls.size());

for (Customer bo:ls)

{

System.out.println(bo.getName());

}

输出结果:

数量:4

李明

刘芳

zhang ming

ZHANG SAN

2、通用情况

要求:根据姓名、地址、备注进行模糊查询,忽略大小写,地址要求开始匹配。

说明:这是通用情况,主要演示改变默认字符串匹配方式、改变默认大小写忽略方式、属性特定查询方式配置、忽略属性列表配置。

//创建查询条件数据对象

Customer customer = new Customer();

customer.setName("zhang");

customer.setAddress("河南省");

customer.setRemark("BB");

//创建匹配器,即如何使用查询条件

ExampleMatcher matcher = ExampleMatcher.matching() //构建对象

.withStringMatcher(StringMatcher.CONTAINING) //改变默认字符串匹配方式:模糊查询

.withIgnoreCase(true) //改变默认大小写忽略方式:忽略大小写

.withMatcher("address", GenericPropertyMatchers.startsWith()) //地址采用“开始匹配”的方式查询

.withIgnorePaths("focus"); //忽略属性:是否关注。因为是基本类型,需要忽略掉

//创建实例

Example ex = Example.of(customer, matcher);

//查询

List ls = dao.findAll(ex);

//输出结果

System.out.println("数量:"+ls.size());

for (Customer bo:ls)

{

System.out.println(bo.getName());

}

输出结果:

数量:2

zhang ming

ZHANG SAN

3、多级查询

要求:查询所有潜在客户

说明:主要演示多层级属性查询

//创建查询条件数据对象

CustomerType type = new CustomerType();

type.setCode("01"); //编号01代表潜在客户

Customer customer = new Customer();

customer.setCustomerType(type);

//创建匹配器,即如何使用查询条件

ExampleMatcher matcher = ExampleMatcher.matching() //构建对象

.withIgnorePaths("focus"); //忽略属性:是否关注。因为是基本类型,需要忽略掉

//创建实例

Example ex = Example.of(customer, matcher);

//查询

List ls = dao.findAll(ex);

//输出结果

System.out.println("数量:"+ls.size());

for (Customer bo:ls)

{

System.out.println(bo.getName());

}

输出结果:

数量:4

李明

李莉

张强

ZHANG SAN

4、查询Null值

要求:地址是null的客户

说明:主要演示改变“Null值处理方式”

//创建查询条件数据对象

Customer customer = new Customer();

//创建匹配器,即如何使用查询条件

ExampleMatcher matcher = ExampleMatcher.matching() //构建对象

.withIncludeNullValues() //改变“Null值处理方式”:包括

.withIgnorePaths("id","name","sex","age","focus","addTime","remark","customerType"); //忽略其他属性

//创建实例

Example ex = Example.of(customer, matcher);

//查询

List ls = dao.findAll(ex);

//输出结果

System.out.println("数量:"+ls.size());

for (Customer bo:ls)

{

System.out.println(bo.getName());

}

输出结果:

数量:2

张强

刘明

七、写在最后

对实例查询的研究及本文的写作,确入投入了精力,因此该文章也赢得了不少的点击率。

但是...但是...就实用性而言,由于“实例查询”的局限性和复杂性,在Spring Data JPA中其实是不实用的。用的最多的还是“简单查询”(因为简单,所以...)和 基于JPA Criteria 的动态查询(可以满足所有需求,没有局限性)。(仅个人观点)

简单查询的两篇博文:

mysql jpa 正则_Spring Data JPA 实例查询相关推荐

  1. Hibernate、JPA、Spring Data JPA,傻傻分不清

    国庆假期接近尾声,明天最后一天了,要开始收收心啦- 今天讲讲一个初学者(或许一些老手)可能没去搞懂的几个概念:Hibernate.JPA.Spring Data JPA 之间的关联. 嘿嘿,前段时间有 ...

  2. jpa 动态查询条件 数组_Spring data jpa 复杂动态查询方式总结

    一.Spring data jpa 简介 首先JPA是Java持久层API,由Sun公司开发, 希望整合ORM技术,实现天下归一.  诞生的缘由是为了整合第三方ORM框架,建立一种标准的方式,目前也是 ...

  3. 在每个运行中运行多个查询_Spring Data JPA的运行原理及几种查询方式

    Spring Data JPA的运行原理: @PersistenceContext(name="entityManagerFactory") private EntityManag ...

  4. jpa调用mysql函数_Spring data jpa 调用存储过程处理返回参数及结果集(示例代码)

    一.环境 1.此随笔内容基于spring boot整合的spring data jpa项目, 2.数据库为mysql 5.7.9版本 二.内容 1. 新建存储过程 pro_query_object B ...

  5. jpa多表联查动态_Spring Data JPA 连表动态条件查询

    多表查询在spring data jpa中有两种实现方式,第一种是利用hibernate的级联查询来实现(使用较为复杂,查询不够灵活),第二种是使用原生sql查询. JPA原生SQL连表查询 @Rep ...

  6. jpa多表联查动态_Spring Data JPA实现动态多表关联查询

    在面向关系型数据库(例如:MySQL)的查询中,动态的.多表关联的查询属于比较复杂的情况.所以,我们只要掌握了这种复杂的查询,当面对其他查询情况时,就能做到胸有成竹. 在java工程中,目前我所了解到 ...

  7. jpa分页查询_spring data jpa 居然提供了这么多查询方式!

    spring data jpa提供了多种查询方式,如下: 方法名称查询 继承Repository接口 测试代码 方法名称中支持的关键字(官方文档提供) 使用JPA命名查询 在User实体中定义jpql ...

  8. java增删改查实例源码_Spring Data JPA 实现简单的CRUD增删改查源码案例

    Spring专题 Spring Data JPA 实现简单的CRUD增删改查源码案例 Spring Data JPA旨在简化JPA基础知识库构建和减少需要与数据库进行通信的代码量.第一部分是如何配置H ...

  9. mysql 主键 最佳实践_Spring Data Jpa + MySQL IDENTITY 主键下批量插入最佳实践

    Spring Data Jpa 虽然可以使用参数调整批量插入,但是仅限于主键策略不是 IDENTITY 的情况下,对于习惯了使用 IDENTITY 的 MySQL 选手来说,批量插入数据直接就悲剧了. ...

最新文章

  1. CentOS之httpd与apache安装区别
  2. Sring AOP(简记)
  3. 【STM32】IIC的基本原理(实例:普通IO口模拟IIC时序读取24C02)(转载)
  4. FLEX:DataGrid分页.
  5. java rsa padding_rsa加密--选择padding模式需要注意的问题。。。
  6. IAP上线后查不到product id
  7. 内存数据库 TimesTen
  8. matlab编写erf函数
  9. win7 与xp 互联步骤
  10. 基于HTML5的移动Web应用——Bootstrap 样式案例:制作百度登录框
  11. java中重命名文件夹名,【Java】对文件或文件夹进行重命名
  12. 小码哥学习感想第一天
  13. Android 多平台AR SDK 集成使用
  14. python用sympy解二元一次方程等数学运算
  15. 西门子840d高级编程手册_斯沃系统手册--西门子高级编程手册_840D_810Di_810D_FM_NC高级篇.pdf...
  16. 【新手教程】如何在Win11上制作一个模仿MacOS的桌面?
  17. 北京十大办公室租赁平台,高性价比
  18. 360随身WiFi在没有网络的情况下打开热点
  19. 人体解析任务 和 Look into Person数据集 (附源码分享)
  20. javaScript canvas从入门到骨灰级玩家(基础篇)

热门文章

  1. 杭电1422 重温世界杯
  2. 一般试卷的纸张大小是多少_国际A4纸尺寸大小是多少?标准A4纸像素分辨率换算方法...
  3. 随想录(机器学习的生产应用)
  4. 随想录(移动app下的生活)
  5. windows c++ cjson 使用_cJSON源码剖析
  6. mysql 多线程并行复制_【MySQL】开启并行复制
  7. oracle 改变受限模式,oracle之受限模式修改
  8. 蓝芯保护卡_有个网友问偶蓝芯卡是目前最好的还原卡?它与传统还原卡的区别在哪里?...
  9. aes ios php,AES算法在PHP和Android和iOS上有所不同
  10. ISA频繁断线的原因和解决方法