前言:
本想在网上找JPA Example的教程文章,发现仅仅只有一些对零散的对模糊查询的一些示例
所以学习了下spring的Example文档,做了以下总结及说明和简单示例,一些方法的使用自己摸索出来的(都有过测试)
肯定有不足之处,望各位大神指出
Interface ExampleMatcher
示例
嵌套类(内部类)
- static class ExampleMatcher.GenericPropertyMatcher
- static class ExampleMatcher.GenericPropertyMatchers
- static interface ExampleMatcher.MatcherConfigurer
- static class ExampleMatcher.MatchMode
- static class ExampleMatcher.NoOpPropertyValueTransformer
- static class ExampleMatcher.NullHandler
- static class ExampleMatcher.StringMatcher
方法
- getIgnoredPaths()
- 返回所有设置忽略匹配 withIgonrePaths(String… ignorePaths) 的字段集合
- 类型:Set
- getMatchMode()
- 返回匹配模式
- ANY
- ALL
- 类型:ExampleMatcher.MatchMode
- 返回匹配模式
- getNullHandler()
- 获取一个空处理的ExampleMatcher
- 类型:ExampleMatcher.NullHandler
以下返回boolean
- isAllMatching()
- 判断匹配模式受否为matchingAll()模式
- isAnyMatching()
- 判断匹配模式受否为matchingAny()模式
- isIgnoreCaseEnabled()
- 判断是否开启了忽略大小写模式
- isIgnoredPath(String path)
- 对一个字段判断是否是设置了忽略匹配模式;也就是设置了 withIgonrePaths(String… ignorePaths) 的字段
以下都是返回ExampleMatcher对象(链式调用)
-
getDefaultStringMatcher()
- 返回默认的ExampleMatcher对象
-
matching()
-
返回一个匹配所有字段的ExampleMatcher对象;源码调用的是matchingAll()方法
-
源码
static ExampleMatcher matching() { return matchingAll(); }
-
示例
ExampleMatcher exampleMatcher = ExampleMatcher.matching() .withMatcher("username", ExampleMatcher.GenericPropertyMatcher::startsWith) .withIgnorePaths("password"); Example<User> of = Example.of(user, exampleMatcher); List<User> all = userRepository.findAll(of);
-
-
matchingAll()
- 如上:返回一个匹配所有字段的ExampleMatcher对象;
-
matchingAny()
-
对任意一个字段进行匹配
-
示例:使用起来和matching()并无区别
ExampleMatcher exampleMatcher = ExampleMatcher.matchingAny() .withMatcher("username", ExampleMatcher.GenericPropertyMatcher::startsWith) .withIgnorePaths("password"); Example<User> of = Example.of(user, exampleMatcher); List<User> all = userRepository.findAll(of);
-
-
withIgnoreCase(boolean defaultIgnoreCase)
-
返回一个默认的ExampleMatcher
- 默认是忽略大小写的
ExampleMatcher.matching().withIgnoreCase(true);
-
源码
public ExampleMatcher withIgnoreCase(boolean defaultIgnoreCase) { return new TypedExampleMatcher(nullHandler, defaultStringMatcher, propertySpecifiers, ignoredPaths, defaultIgnoreCase, mode); }
-
-
withIgnoreCase(String… propertyPaths)
-
对一个或多个字段设置忽略大小写
ExampleMatcher.matching().withIgnoreCase("username");
-
-
withIgonrePaths(String… ignorePaths)
-
对一个或多个字段设置,则此字段不受其它匹配影响,也就是说其他任何匹配模式不对这个字段生效
-
如:不管设置了什么匹配模式,都不会对password字段生效
ExampleMatcher exampleMatcher = ExampleMatcher.matching() .withMatcher("username", ExampleMatcher.GenericPropertyMatcher::startsWith) .withIgnorePaths("password");
-
-
withIgnoreNullValues
- 返回一个对被忽略字段 Null空值处理的ExampleMatcher对象
-
withIncludeNullValues()
- 返回一个对字段 Null空值处理的ExampleMatcher对象
-
withMatcher(String propertyPath, ExampleMatcher.GenericPropertyMatcher gennericPropertyMatcher)
- propertyPath 字段名
- gennericPropertyMatcher 匹配规则
-
withStringMatcher(ExampleMatcher.StringMatcher defaultStringMatcher)
-
如:返回一个匹配开始的字符串的ExampleMatcher
-
ExampleMatcher stringMatcher = ExampleMatcher.matching().withStringMatcher(ExampleMatcher.StringMatcher.STARTING);
-
-
withTransformer(String propertyPath, ExampleMatcher.PropertyValueTransformer propertyValueTransformer)
- propertyPath:字段名
- propertyValueTransformer:转换规则
ExampleMatcher username = ExampleMatcher.matching().withTransformer("username", o -> Optional.of("jpa-1"));
与如下效果一致
ExampleMatcher.GenericPropertyMatcher transform = new ExampleMatcher.GenericPropertyMatcher().transform(o -> Optional.of("jpa-1")); ExampleMatcher.matching().withMatcher("username",transform)
public static class ExampleMatcher.GenericPropertyMatcher
注:返回值都是ExampleMatcher.GenericPropertyMatcher
- contains() 模糊包含匹配;
User user = new User();
user.setUsername("test");
ExampleMatcher exampleMatcher = ExampleMatcher.matching()
.withMatcher("username",
//对username字段进行包含模式匹配
ExampleMatcher.GenericPropertyMatcher::contains)
//不对password字段进行任何处理
.withIgnorePaths("password");
Example<User> of = Example.of(user, exampleMatcher);
List<User> all = userRepository.findAll(of);
System.out.println(all);
-
endsWith() 后缀模糊匹配
- 以上都是用::方法引用
- 这次用new 对象的方式来创建ExampleMatcher
//对字段结尾模糊批匹配 ExampleMatcher.GenericPropertyMatcher endsWith = new ExampleMatcher.GenericPropertyMatcher().endsWith(); ExampleMatcher exampleMatcher = ExampleMatcher.matchingAny() .withMatcher("username", endsWith) .withIgnoreCase("username") .withIgnorePaths("password");
以下用法和上面都一样,只是匹配模式不同而已
-
exact() 精确匹配
-
ignoreCase(boolean ignoreCase)
- 设置忽略大小写为 true;也就是忽略大小写
-
caseSensitive()
- 设置忽略大小写为 false;也就是不忽略大小写
-
startsWith()
- 对开头的字符串模糊匹配
-
storeDefaultMatching()
- 默认匹配模式
-
regex()
- 将字符串视为正则表达式模式进行匹配
-
of(ExampleMatcher.StringMatcher stringMatcher)
-
ExampleMatcher.StringMatcher提供了如下枚举
-
CONTAINING
- 匹配包含的字符串
-
DEFAULT
- 默认匹配模式
-
ENDING
- 匹配结尾的字符串
-
EXACT
- 匹配精确的字符串
-
REGEX
- 将字符串视为正则表达式进行匹配
-
STARTING
- 匹配开始的字符串
-
-
示例
ExampleMatcher exampleMatcher = ExampleMatcher.matchingAny() //ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.STARTING)) .withMatcher("username",ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.STARTING)) .withIgnoreCase("username") .withIgnorePaths("password");
ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.STARTING)
-
-
of(ExampleMatcher.StringMatcher stringMatcher, boolean ignoreCase)
-
和上一个一样,只是多了一个boolean来指定忽略大小写
ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.STARTING,false))
-
-
stringMatcher(ExampleMatcher.StringMatcher stringMatcher)
-
ExampleMatcher.StringMatcher提供了如下枚举
-
CONTAINING
- 匹配包含的字符串
-
DEFAULT
- 默认匹配模式
-
ENDING
- 匹配结尾的字符串
-
EXACT
- 匹配精确的字符串
-
REGEX
- 将字符串视为正则表达式进行匹配
-
STARTING
- 匹配开始的字符串
-
示例
//通过ExampleMatcher.StringMatcher.XXX定义匹配模式 ExampleMatcher.StringMatcher defaultMode = ExampleMatcher.StringMatcher.DEFAULT; ExampleMatcher stringMatcher = ExampleMatcher.matching().withStringMatcher(ExampleMatcher.StringMatcher.STARTING); ExampleMatcher exampleMatcher = ExampleMatcher.matchingAny() .withMatcher("username",ExampleMatcher.GenericPropertyMatcher::startsWith) //将defaultMode传入 .withMatcher("username",ExampleMatcher.GenericPropertyMatcher.of(defaultMode,true)) .withMatcher("username", endsWith) .withIgnoreCase("username") .withIgnorePaths("password");
-
-
transform(ExampleMatcher.PropertyValueTransformer propertyValueTransforme)
-
在查询之前对属性值进行转换
-
示例:将传过来的参数test替换为jpa-1
ExampleMatcher.GenericPropertyMatcher().transform(o -> Optional.of("jpa-1"));
User user = new User(); user.setUsername("test"); ExampleMatcher.GenericPropertyMatcher transform = new ExampleMatcher.GenericPropertyMatcher().transform(o -> Optional.of("jpa-1")); ExampleMatcher exampleMatcher = ExampleMatcher.matching() .withMatcher("username", ExampleMatcher.GenericPropertyMatcher::startsWith) .withMatcher("username", transform) .withIgnorePaths("password"); Example<User> of = Example.of(user, exampleMatcher); List<User> all = userRepository.findAll(of); System.out.println(all);
-
打印结果
[User(id=7, username=jpa-1, password=123)]
若没有使用替换
结果为:
[User(id=9, username=test, password=test)]
-
注意:这里Optional.of(“jpa-1”)的jpa-1必须精确完整,且写了transform后 其它模糊匹配失效
-
static class ExampleMatcher.GenericPropertyMatchers
只定义了如下方法
方法
- caseSensitive()
- 不忽略大小写
- ignoreCase()
- 忽略大小写
- contains()
- 匹配包含字符串
- endsWith()
- 匹配结尾字符串
- exact()
- 精确匹配字符串
- reges()
- 将字符串作为正则表达式进行匹配
- startsWith()
- 匹配结尾字符串
- storeDefaultMatching()
- 默认匹配模式
使用和功能都和ExampleMatcher.GenericPropertyMatcher类的方法一样
static interface ExampleMatcher.MatcherConfigurer<T>
-
第一步
写一个类实现ExampleMatcher.MatcherConfigurer<User>这个接口package com.live.model; import org.springframework.data.domain.ExampleMatcher; public class MyMatching implements ExampleMatcher.MatcherConfigurer<User> { @Override public void configureMatcher(User matcher) { matcher.setUsername("jpa"); } }
泛型为要操作的的Entity
即:
package com.live.model; import lombok.Data; import javax.persistence.*; @Entity @Table(name = "jpa_user") @Data public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; @Column(name = "jpa_username",length = 40) private String username; @Column(name = "jap_password") private String password; }
-
第二步: 调用MyMatching
User user = new User(); user.setUsername("test"); ExampleMatcher exampleMatcher = ExampleMatcher.matchingAny() .withMatcher("username", ExampleMatcher.GenericPropertyMatcher::startsWith) .withIgnorePaths("password"); //调用我们自己实现MyMatching类的congifureMatcher方法,将user传入 new MyMatching().configureMatcher(user); Example<User> of = Example.of(user,exampleMatcher); List<User> all = userRepository.findAll(of); System.out.println(all);
-
结果
- new MyMatching().configureMatcher(user)
- 将user的username=“test"
- 设置为了”jpa“
- 所以结果为
[ User(id=8, username=jpa-2, password=234), User(id=7, username=jpa-1, password=123), User(id=6, username=jpa-dead, password=123123123123), User(id=5, username=jpa-result, password=12345) ]
static class ExampleMatcher.MatchMode
方法
-
static ExampleMatcher.MatchMode valueOf(String name)
-
根据name返回匹配模式
-
如:
ExampleMatcher.MatchMode.valueOf("ANY")
-
-
static ExampleMatcher.MatchMode[] values()
-
返回所有匹配模式
-
如:
ExampleMatcher.MatchMode[] values = ExampleMatcher.MatchMode.values();
-
打印结果
[ANY,ALL]
-
static ExampleMatcher.NoOpPropertyValueTransofrmer
方法
-
static ExampleMatcher.NoOpPropertyValueTransformer valueOf(String name)
-
返回具有指定名称的此类型的枚举常量
-
如:
ExampleMatcher.NoOpPropertyValueTransformer instance = ExampleMatcher.NoOpPropertyValueTransformer.valueOf("INSTANCE");
-
-
static ExampleMatcher.NoOpPropertyValueTrasformer[] values()
-
返回一个数组,该数组包含这个枚举类型的常量,按声明的顺序排列
ExampleMatcher.NoOpPropertyValueTransformer[] values = ExampleMatcher.NoOpPropertyValueTransformer.values();
-
打印结果:只有一个
[INSTANCE]
-
-
Optional apply(Optional source)
-
定义Function
public class MyFunction implements Function<Optional<User>, User> { @Override public User apply(Optional<User> user) { User user1 = new User(); user1.setUsername("apply-username"); user1.setPassword("apply-password"); user1.setId(200); return user1; } }
-
通过ExampleMatcher.NoOpPropertyValueTransformer.valueOf(“INSTANCE”);获取 ExampleMatcher.NoOpPropertyValueTransformer
-
再调用apply();进行消费
instance.apply(Optional.ofNullable(new MyFunction().apply(Optional.of(user))));
User user = new User(); user.setUsername("test"); ExampleMatcher.NoOpPropertyValueTransformer instance = ExampleMatcher.NoOpPropertyValueTransformer.valueOf("INSTANCE"); Optional<Object> instance = instance.apply(Optional.ofNullable(new MyFunction().apply(Optional.of(user)))); //通过get()将instance强转为User User o = (User) instance.get(); System.out.println(o);
-
打印结果
User(id=200, username=apply-username, password=apply-password)
-
ExampleMatcher.NullHandler
方法
- static ExampleMatcher.NullHandler valueOf(String name)
- 根据参数name,返回一个NullHandler
- name可写的有:
- INCLUDE
- IGNORE
- static ExampleMatcher.NullHandler values()
- 结果
- [INCLUDE,IGNORE]
- 结果
static class ExampleMatcher.StringMatcher
方法
- static ExampleMatcher.StringMatcher valueOf(String name)
- 根据参数name,返回对应的ExampleMatcher.StringMatcher
- static ExampleMatcher.StringMatcher values()
- 返回ExampleMatcher.StringMatcher[]数组
枚举
- CONTAINING
- 匹配包含的字符串
- DEFAULT
- 默认匹配模式
- ENGING
- 匹配结尾的字符串
- EXACT
- 精确匹配字符串
- REGEX
- 将字符串作为正则表达式匹配
- STARTING
- 匹配开头的字符串
使用
ExampleMatcher exampleMatcher = ExampleMatcher.matching()
//这个通过ExampleMatcher.GenericPropertyMatcher方法引用startWith来模糊匹配开头的字符串
.withMatcher("username", ExampleMatcher.GenericPropertyMatcher::startsWith)
//这个通过ExampleMatcher.GenericPropertyMatcher.of()方法传入ExampleMatcher.StringMatcher.STARTING来模糊匹配开头的字符串
.withMatcher("username", ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.STARTING))
.withIgnorePaths("password");
Example<User> example = Example.of(user);
List<User> all = userRepository.findAll(example);
示例
Entity
package com.live.model;
import lombok.Data;
import javax.persistence.*;
@Entity
@Table(name = "jpa_user")
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "jpa_username",length = 40)
private String username;
@Column(name = "jap_password")
private String password;
}
数据库
根据前缀模糊查询
- /findAllStartsWith/jpa
@GetMapping("/findAllStartsWith/{username}")
public List<User> findAllByUsername(@PathVariable(value = "username") String username) {
User user = new User();
user.setUsername(username);
ExampleMatcher matching = ExampleMatcher.matching()
//这个通过ExampleMatcher.GenericPropertyMatcher方法引用startWith来模糊匹配开头的字符串
.withMatcher("username", ExampleMatcher.GenericPropertyMatcher::startsWith)
//这个通过ExampleMatcher.GenericPropertyMatcher.of()方法传入ExampleMatcher.StringMatcher.STARTING来模糊匹配开头的字符串
//.withMatcher("username", ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.STARTING))
//不对password字段处理
.withIgnorePaths("password");
Example<User> example = Example.of(user, matching);
return userRepository.findAll(example);
}
-
结果
[ User(id=8, username=jpa-2, password=234), User(id=7, username=jpa-1, password=123), User(id=6, username=jpa-dead, password=123123123123), User(id=5, username=jpa-result, password=12345) ]
根据后缀模糊查询
-
/findAllEndswith/dead
@GetMapping("/findAllEndswith/{username}") public List<User> findAllByUsername(@PathVariable(value = "username") String username) { User user = new User(); user.setUsername(username); //也可以将匹配模式单独写出来 ExampleMatcher.GenericPropertyMatcher endsWith = new ExampleMatcher.GenericPropertyMatcher().endsWith(); ExampleMatcher matching = ExampleMatcher.matching() .withMatcher("username", endsWith) //不对password字段处理 .withIgnorePaths("password"); Example<User> example = Example.of(user, matching); return userRepository.findAll(example); }
-
结果
[ User(id=6, username=jpa-dead, password=123123123123) ]
根据包含模式查询
-
/findAllContains/e
@GetMapping("/findAllContains/{username}") public List<User> findAllByUsername(@PathVariable(value = "username") String username) { User user = new User(); user.setUsername(username); ExampleMatcher matching = ExampleMatcher.matching() //这个通过ExampleMatcher.GenericPropertyMatcher方法引用contains来匹配包含的字符串 .withMatcher("username", ExampleMatcher.GenericPropertyMatcher::contains) //这个通过ExampleMatcher.GenericPropertyMatcher.of()方法传入ExampleMatcher.StringMatcher.CONTAINING来匹配保安的字符串 //.withMatcher("username", ExampleMatcher.GenericPropertyMatcher.of(ExampleMatcher.StringMatcher.CONTAINING)) //不对password字段处理 .withIgnorePaths("password"); Example<User> example = Example.of(user, matching); return userRepository.findAll(example); }
-
结果
[ User(id=6, username=jpa-dead, password=123123123123), User(id=5, username=jpa-result, password=12345), User(id=9, username=test, password=test) ]
在查询前更改属性值
-
/findOneTransform/jpa
- 注意:Optional.of(“jpa-1”)的”jpa-1“必须精确完整,且是更改属性后,模糊查询失效
@GetMapping("/findOneTransform/{username}") public List<User> findAllByUsername(@PathVariable(value = "username") String username) { User user = new User(); user.setUsername(username); ExampleMatcher.GenericPropertyMatcher transform = new ExampleMatcher.GenericPropertyMatcher().transform(o -> Optional.of("jpa-1")); ExampleMatcher stringMatcher = ExampleMatcher.matching().withStringMatcher(ExampleMatcher.StringMatcher.STARTING); ExampleMatcher exampleMatcher = ExampleMatcher.matchingAny() .withMatcher("username", stringMatcher) .withMatcher("username", transform) //对username字段忽略大小写 .withIgnoreCase("username") //不对password字段处理 .withIgnorePaths("password"); new MyMatching().configureMatcher(user); Example<User> of = Example.of(user, exampleMatcher); List<User> all = userRepository.findAll(of); System.out.println(all); }
-
结果
[ User(id=7, username=jpa-1, password=123) ]
精确查询
-
/findOneExact/jpa-dead
@GetMapping("/findOneExact/{username}") public List<User> findAllByUsername(@PathVariable(value = "username") String username) { User user = new User(); user.setUsername(username); ExampleMatcher exampleMatcher = ExampleMatcher.matchingAny() .withMatcher("username", ExampleMatcher.GenericPropertyMatcher::exact) .withIgnorePaths("password"); Example<User> of = Example.of(user,exampleMatcher); Optional<User> user = userRepository.findOne(of); System.out.println(user); }
-
结果
Optional[ User( id=6, username=jpa-dead, password=123123123123 ) ]