jpa动态sql拼接_09SpringDataJPA动态SQL及自定义Repository

更新时间:2023-05-28 08:31:42 阅读: 评论:0

jpa动态sql拼接_09SpringDataJPA动态SQL及⾃定义
Repository
Spring Data JPA动态SQL及⾃定义Repository
从 JpaRepository 开始的⼦类,都是 Spring Data 项⽬对 JPA 实现的封装与扩展。JpaRepository 本⾝继承PagingAndSortingRepository 接⼝,是针对 JPA 技术的接⼝,提供 flush()、saveAndFlush()、deleteInBatch()、deleteAllInBatch() 等⽅法。我们来看⼀下 UML 来对 JpaRespository 有个整体的认识。
QueryByExampleExecutor的使⽤
按实例查询(QBE)是⼀种⽤户友好的查询技术,具有简单的接⼝。它允许动态查询创建,并且不需要编写包含字段名称的查询。只需要继承JpaRepository接⼝后,⾃动拥有了实例查询⽅法。
public interface QueryByExampleExecutor {
// 根据实例创建⼀个对象
Optional findOne(Example var1);
// 根据实例查找⼀批对象
Iterable findAll(Example var1);
// 根据实例查找⼀批对象,且排序
Iterable findAll(Example var1, Sort var2);
// 根据实例查找⼀批对象,且排序和分页
Page findAll(Example var1, Pageable var2);
// 根据实例查找,返回符合条件的个数
long count(Example var1);
// 根据实例查找,判断是否有符合条件的对象短裙用英语怎么说
boolean exists(Example var1);
}
需要掌握操作Example的⽤法和API
public interface Example {
static Example of(T probe) {
return new TypedExample(probe, ExampleMatcher.matching());
}
徐州环球雅思static Example of(T probe, ExampleMatcher matcher) {
return new TypedExample(probe, matcher);
}
T getProbe();
ExampleMatcher getMatcher();
default Class getProbeType() {
Probe().getClass());
}
梁上君子翻译}
sweet是什么意思中文
在源码中Example主要包括三个内容:
Probe:这是具有填充字段的域对象实际实体类,即查询条件的封装类。必填
ExampleMatcher:ExampleMatcher有关于匹配特定字段的匹配规则,他可以重复在多个实例中。必填,如果不填为默认的
Example:Examle由探针和ExampleMatcher组成的。它⽤于创建查询。
QueryByExampleExecutor⽰例
//创建查询条件数据对象
传真格式Customer customer = new Customer();
customer.tName("Jack");
customer.tAddress("上海");
坚持到底的英文//创建匹配器,即如何使⽤查询条件
ExampleMatcher matcher = ExampleMatcher.matching() //构建对象
.withMatcher("name", GenericPropertyMatchers.startsWith()) //姓名采⽤“开始匹配”的⽅式查询
.withIgnorePaths("focus"); //忽略属性:是否关注。因为是基本类型,需要忽略掉
//创建实例
Example ex = Example.of(customer, matcher);
//查询
List ls = dao.findAll(ex);
//输出结果
for (Customer bo:ls)
{
System.out.Name());
}
上⾯例⼦中,是这样创建“实例”的:Example ex = Example.of(customer, matcher);可以看到,Example 对象由 customer 和matcher 共同创建,为讲解⽅便,再来结合案例先来明确⼀些定义。
Probe:实体对象,在持久化框架中与 Table 对应的域对象,⼀个对象代表数据库表中的⼀条记录,如上例中 Customer 对象。在构建查询条件时,⼀个实体对象代表的是查询条件中的“数值”部分,如要查询姓“Jack”的客户,实体对象只能存储条件值“Jack”。
ExampleMatcher:匹配器,它是匹配“实体对象”的,表⽰了如何使⽤“实体对象”中的“值”进⾏查询,它代表的是“查询⽅式”,解释了如何去查的问题。例如,要查询姓“刘”的客户,即姓名以“刘”开头的客户,该对象就表⽰了“以某某开头的”这个查询⽅式,如上例中 withMatcher("name", GenericPropertyMatchers.startsWith())。
Example:实例对象,代表的是完整的查询条件。由实体对象(查询条件值)和匹配器(查询⽅式)共同创建。
再来理解“实例查询”,顾名思义,就是通过⼀个例⼦来查询,要查询的是 Customer 对象,查询条件也是⼀个 Customer 对象,通过⼀个现有的客户对象作为例⼦,查询和这个例⼦相匹配的对象。
QueryByExampleExecutor 的特点及约束
⽀持动态查询:即⽀持查询条件个数不固定的情况,如客户列表中有多个过滤条件,⽤户使⽤时在“地址”查询框中输⼊了值,就需要按地址进⾏过滤,如果没有输⼊值,就忽略这个过滤条件。对应的实现是,在构建查询条件 Customer 对象时,将 address 属性值置具体的条件值或置为 null。
不⽀持过滤条件分组:即不⽀持过滤条件⽤ or(或)来连接,所有的过滤查件,都是简单⼀层的⽤ and(并且)连接,如 firstname = ?0 or (firstname = ?1 and lastname = ?2)。
仅⽀持字符串的开始/包含/结束/正则表达式匹配和其他属性类型的精确匹配。查询时,对⼀个要进⾏匹配的属性(如:姓名 name),只能传⼊⼀个过滤条件值,如以 Customer 为例,要查询姓“刘”的客户,“刘”这个条件值就存储在表⽰条件对象的 Customer 对象的 name 属性中,针对于“姓名”的过滤也只有这么⼀个存储过滤值的位置,没办法同时传⼊两个过滤值。正是由于这个限制,有些查询是没办法⽀持的,例如要查询某个时间段内添加的客户,对应的属性是 addTime,需要传⼊“开始时间”和“结束时间”两个条件值,⽽这种查询⽅式没有存两个值的位置,所以就没办法完成这样的查询。
ExampleMatcher 源码解读
public class ExampleMatcher {
NullHandler nullHandler;
StringMatcher defaultStringMatcher; //默认
boolean defaultIgnoreCa; //默认⼤⼩写忽略⽅式
PropertySpecifiers propertySpecifiers; //各属性特定查询⽅式
Set ignoredPaths; //忽略属性列表
//Null值处理⽅式,通过构造⽅法,我们发现默认忽略
NullHandler nullHandler;
//字符串匹配⽅式,通过构造⽅法可以看出默认是DEFAULT(默认,效果同EXACT),EXACT(相等)
StringMatcher defaultStringMatcher;
//各属性特定查询⽅式,默认⽆特殊指定的。
PropertySpecifiers propertySpecifiers;
//忽略属性列表,默认⽆。
Set ignoredPaths;
//⼤⼩写忽略⽅式,默认不忽略。
boolean defaultIgnoreCa;
@Wither(AccessLevel.PRIVATE) MatchMode mode;
//通⽤、内部、默认构造⽅法。
private ExampleMatcher() {
this(NullHandler.IGNORE, StringMatcher.DEFAULT, new PropertySpecifiers(), ptySet(), fal,
泡泡少儿教育
MatchMode.ALL);
communication
}
//Example的默认匹配⽅式
public static ExampleMatcher matching() {
return matchingAll();
}
public static ExampleMatcher matchingAll() {
return new ExampleMatcher().withMode(MatchMode.ALL);witch是什么意思
}
......
}
关键属性分析
nullHandler:Null 值处理⽅式,枚举类型,有两个可选值,INCLUDE(包括)、IGNORE(忽略)。
标识作为条件的实体对象中,⼀个属性值(条件值)为 Null 时,是否参与过滤;
当该选项值是 INCLUDE 时,表⽰仍参与过滤,会匹配数据库表中该字段值是 Null 的记录;
若为 IGNORE 值,表⽰不参与过滤。
defaultStringMatcher:默认字符串匹配⽅式,枚举类型,有 6 个可选值,DEFAULT(默认,效果同 EXACT)、EXACT(相等)、STARTING(开始匹配)、ENDING(结束匹配)、CONTAINING(包含,模糊匹配)、REGEX(正则表达式)。
该配置对所有字符串属性过滤有效,除⾮该属性在 propertySpecifiers 中单独定义⾃⼰的匹配⽅式。
defaultIgnoreCa:默认⼤⼩写忽略⽅式,布尔型,当值为 fal 时,即不忽略,⼤⼩不相等。
该配置对所有字符串属性过滤有效,除⾮该属性在 propertySpecifiers 中单独定义⾃⼰的忽略⼤⼩写⽅式。
propertySpecifiers:各属性特定查询⽅式,描述了各个属性单独定义的查询⽅式,每个查询⽅式中包含4个元素:属性名、字符串匹配⽅式、⼤⼩写忽略⽅式、属性转换器。
如果属性未单独定义查询⽅式,或单独查询⽅式中,某个元素未定义(如字符串匹配⽅式),则采⽤ ExampleMatcher 中定义的默认值,即上⾯介绍的 defaultStringMatcher 和 defaultIgnoreCa 的值。
ignoredPaths:忽略属性列表,忽略的属性不参与查询过滤。
(3)字符串匹配举例
字符串匹配⽅式
对应 JPQL 的写法
Default& 不忽略⼤⼩写
firstname=?1
Exact& 忽略⼤⼩写
LOWER(firstname) = LOWER(?1)
Staring& 忽略⼤⼩写
LOWER(firstname) like LOWER(?0)+'%'
Ending& 不忽略⼤⼩写
firstname like '%'+?1
Containing 不忽略⼤⼩写
firstname like '%'+?1+'%'
QueryByExampleExecutor 使⽤场景 & 实际的使⽤
使⽤场景
使⽤⼀组静态或动态约束来查询数据存储、频繁重构域对象,⽽不⽤担⼼破坏现有查询、简单的查询的使⽤场景,有时候还是挺⽅便的。
实际使⽤中我们需要考虑的因素
查询条件的表⽰,有两部分,⼀是条件值,⼆是查询⽅式。条件值⽤实体对象(如 Customer 对象)来存储,相对简单,当页⾯传⼊过滤条件值时,存⼊相对应的属性中,没⼊传⼊时,属性保持默认值。查询⽅式是⽤匹配器 ExampleMatcher 来表⽰,情况相对复杂些,需要考虑的因素有以下⼏个:
(1)Null 值的处理
当某个条件值为 Null时,是应当忽略这个过滤条件呢,还是应当去匹配数据库表中该字段值是 Null 的记录?over flow
Null 值处理⽅式:默认值是 IGNORE(忽略),即当条件值为 Null 时,则忽略此过滤条件,⼀般业务也是采⽤这种⽅式就可满⾜。当需要查询数据库表中属性为 Null 的记录时,可将值设为 INCLUDE,这时,对于不需要参与查询的属性,都必须添加到忽略列表(ignoredPaths)中,否则会出现查不到数据的情况。
(2)基本类型的处理
如客户 Customer 对象中的年龄 age 是 int 型的,当页⾯不传⼊条件值时,它默认是0,是有值的,那是否参与查询呢?
关于基本数据类型处理⽅式:实体对象中,避免使⽤基本数据类型,采⽤包装器类型。如果已经采⽤了基本类型,⽽这个属性查询时不需要进⾏过滤,则把它添加到忽略列表(ignoredPaths)中。
(3)忽略某些属性值
⼀个实体对象,有许多个属性,是否每个属性都参与过滤?是否可以忽略某些属性?
ignoredPaths:虽然某些字段⾥⾯有值或者设置了其他匹配规则,只要放在 ignoredPaths 中,就会忽略此字段的,不作为过滤条件。
(4)不同的过滤⽅式
同样是作为 String 值,可能“姓名”希望精确匹配,“地址”希望模糊匹配,如何做到?
默认配置和特殊配置混合使⽤:默认创建匹配器时,字符串采⽤的是精确匹配、不忽略⼤⼩写,可以通过操作⽅法改变这种默认匹配,以满⾜⼤多数查询条件的需要,如将“字符串匹配⽅式”改为 CONTAINING(包含,模糊匹配),这是⽐较常⽤的情况。对于个别属性需要特定的查询⽅式,可以通过配置“属性特定查询⽅式”来满⾜要求,设置 propertySpecifiers 的值即可。
(5)⼤⼩写匹配
字符串匹配时,有时可能希望忽略⼤⼩写,有时则不忽略,如何做到?
defaultIgnoreCa:忽略⼤⼩的⽣效与否,是依赖于数据库的。例如 MySQL 数据库中,默认创建表结构时,字段是已经忽略⼤⼩写的,所以这个配置与否,都是忽略的。如果业务需要严格区分⼤⼩写,可以改变数据库表结构属性来实现。
实际使⽤案例说明
(1)⽆匹配器的情况
要求:查询地址是“河南省郑州市”,且重点关注的客户。
说明:使⽤默认匹配器就可以满⾜查询条件,则不需要创建匹配器。
//创建查询条件数据对象
Customer customer = new Customer();
customer.tAddress("河南省郑州市");
customer.tFocus(true);
//创建实例
Example ex = Example.of(customer);
//查询

本文发布于:2023-05-28 08:31:42,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/90/125550.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:查询   条件   对象   属性
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图