前言:
本想在网上找JPA Example的教程文章,发现仅仅只有一些对零散的对模糊查询的一些示例
所以学习了下spring的Example文档,做了以下总结及说明和简单示例,一些方法的使用自己摸索出来的(都有过测试)
肯定有不足之处,望各位大神指出
spring官方文档
嵌套类(内部类)
方法
以下返回boolean
以下都是返回ExampleMatcher对象(链式调用)
getDefaultStringMatcher()
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()
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
withIncludeNullValues()
withMatcher(String propertyPath, ExampleMatcher.GenericPropertyMatcher gennericPropertyMatcher)
withStringMatcher(ExampleMatcher.StringMatcher defaultStringMatcher)
如:返回一个匹配开始的字符串的ExampleMatcher
ExampleMatcher stringMatcher = ExampleMatcher.matching().withStringMatcher(ExampleMatcher.StringMatcher.STARTING);
withTransformer(String propertyPath, ExampleMatcher.PropertyValueTransformer 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)
注:返回值都是ExampleMatcher.GenericPropertyMatcher
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() 后缀模糊匹配
//对字段结尾模糊批匹配
ExampleMatcher.GenericPropertyMatcher endsWith = new ExampleMatcher.GenericPropertyMatcher().endsWith();
ExampleMatcher exampleMatcher = ExampleMatcher.matchingAny()
.withMatcher("username", endsWith)
.withIgnoreCase("username")
.withIgnorePaths("password");
以下用法和上面都一样,只是匹配模式不同而已
exact() 精确匹配
ignoreCase(boolean ignoreCase)
caseSensitive()
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后 其它模糊匹配失效
只定义了如下方法
使用和功能都和ExampleMatcher.GenericPropertyMatcher类的方法一样
第一步
写一个类实现ExampleMatcher.MatcherConfigurer
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);
结果
[
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 ExampleMatcher.MatchMode valueOf(String name)
根据name返回匹配模式
如:
ExampleMatcher.MatchMode.valueOf("ANY")
static ExampleMatcher.MatchMode[] values()
返回所有匹配模式
如:
ExampleMatcher.MatchMode[] values = ExampleMatcher.MatchMode.values();
打印结果
[ANY,ALL]
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 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;
}
@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
@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
)
]