springjpa合集地址:https://www.jianshu.com/nb/38441578
先看看JpaRepository的继承树,从继承树可以看出来JapRepository除了继承了Repository那边的路线外,还继承了一个新的接口——QueryByExampleExecutor
![](https://img.haomeiwen.com/i18052029/d3c540cfc5bd3800.png)
QueryByExampleExecutor
很多时候我们的crud项目中有复杂查询功能,页面有很多的查询字段,这些字段都是表结构的某个字段。
QueryByExampleExecutor接口
QueryByExampleExecutor接口能实现较为简单的上述功能。
public interface QueryByExampleExecutor<T> {
<S extends T> Optional<S> findOne(Example<S> example);
<S extends T> Iterable<S> findAll(Example<S> example);
<S extends T> Iterable<S> findAll(Example<S> example, Sort sort);
<S extends T> Page<S> findAll(Example<S> example, Pageable pageable);
<S extends T> boolean exists(Example<S> example);
}
我们将关注点放在findAll(Example<S> example)方法上,它接收一个Example实例,这个实例就是查询条件,它由具体的表对象而来。这个方法的返回值是Iterable对象,需要进行转换后才能传递到前端。
Example接口
Example提供了两个静态方法用于将表对象转换成Example对象
public interface Example<T> {
static <T> Example<T> of(T probe) {
return new TypedExample<>(probe, ExampleMatcher.matching());
}
static <T> Example<T> of(T probe, ExampleMatcher matcher) {
return new TypedExample<>(probe, matcher);
}
//省略...
}
1. of(T probe)
//举个例子,我们要查询用户中年龄等于12,城市在南京,姓名等于张三的用户。
User user=new User();
user.setAge(12);
user.setCity("南京");
user.setName("张三");
Example example=Example.of(user);
Iterable<User> users=userRepository.findAll(example);
第一种是精确值查询,所有不为null的字段(空字符串不算null)都会作为条件进行查询。
2. of(probe,match)
第二种和第一种的区别就是多了一个ExampleMatcher,它是一个匹配器,用于表示具体怎么匹配。它可以对字符串条件做处理,例如模糊查询。注意非字符串条件无法做处理,只能精确查询。
//例如,我们要查询姓张的用户---> name like '张%'
User user=new User();
user.setName("张");
//创建一个匹配器,并设置姓名只要以给的条件开始就可以,不需要精确查询
ExampleMatcher matcher = ExampleMatcher.matching()
.withMatcher("name", ExampleMatcher.GenericPropertyMatchers.startsWith())
Example example=Example.of(user,matcher);
Iterable<User> users=userRepository.findAll(example);
ExampleMatcher接口
public interface ExampleMatcher {
static ExampleMatcher matching() {
return matchingAll();
}
static ExampleMatcher matchingAny() {
return new TypedExampleMatcher().withMode(MatchMode.ANY);
}
static ExampleMatcher matchingAll() {
return new TypedExampleMatcher().withMode(MatchMode.ALL);
}
//...
}
ExampleMatcher接口提供了三个静态方法用于创建一个匹配器,观察这三个方法,其实区别就是any和all的区别。
any指的是所有的条件只要有一个满足就筛选出来。---> where age=12 or city='南京' or name like '张三%'。
all指的是所有的条件都满足才筛选出来。---> where age=12 and city='南京' and name like '张三%'。
创建完实例以后我们可以采用链式编程的方式追加规则。例如
ExampleMatcher matcher = ExampleMatcher.matching()
//where name like 'XXX%'
.withMatcher("name", ExampleMatcher.GenericPropertyMatchers.startsWith())
//where name like '%XXX'
.withMatcher("name", ExampleMatcher.GenericPropertyMatchers.endsWith())
//where name like '%XXX%'
.withMatcher("name", ExampleMatcher.GenericPropertyMatchers.contains())
//name忽略大小写
.withMatcher("name", ExampleMatcher.GenericPropertyMatchers.ignoreCase())
//name大小写敏感,不忽略大小写,默认
.withMatcher("name", ExampleMatcher.GenericPropertyMatchers.caseSensitive())、
//name正则查询
.withMatcher("name", ExampleMatcher.GenericPropertyMatchers.regex())
//忽略id和age条件,即使id和age不为空也不作为查询条件
.withIgnorePaths("id", "age")
//忽略大小写
.withIgnoreCase("name","city")
//忽略null值条件(默认)
.withIgnoreNullValues()
//不忽略null值条件,如果条件为null,那么就按照is null查询
.withIncludeNullValues();
JpaRepository
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
List<T> findAll();
List<T> findAll(Sort var1);
List<T> findAllById(Iterable<ID> var1);
<S extends T> List<S> saveAll(Iterable<S> var1);
void flush();
<S extends T> S saveAndFlush(S var1);
void deleteInBatch(Iterable<T> var1);
void deleteAllInBatch();
T getOne(ID var1);
<S extends T> List<S> findAll(Example<S> var1);
<S extends T> List<S> findAll(Example<S> var1, Sort var2);
}
除了继承的PagingAndSortingRepository和QueryByExampleExecutor接口外,还增加了一些新的方法,例如皮批量增加删除之类。继承JpaRepository以后findAll方法返回的是List,不用再转换了
网友评论