Query By Example(QBE)即(通过例子进行查询)的简称。此处讲的是springdata jpa中的实现,springdata jpa中通过QueryByExampleExecutor进行实现。
springdata版本为2.1.5.RELEASE。
首先创建一个springboot工程,过程比较简单,此处忽略,需要注意的是需要添加JPA的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
同时需要进行数据源及JPA配置,可以参照https://www.jianshu.com/p/e2e5e6bf9755。

此处QBE的查询操作主要通过Example实现,Example实例的创建主要包含以下两种方式:

下面正式进入开发测试阶段:
1、创建实体
@Entity
@Table(name="t_person")
public class Person implements Serializable{
private static final long serialVersionUID = 1258045451015846461L;
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column
private Integer personId;
@Column
private String personNo;
@Column
private String name;
@Temporal(TemporalType.DATE)
@Column
private Date birth;
@Column
private String email;
public Integer getPersonId() {
return personId;
}
public void setPersonId(Integer personId) {
this.personId = personId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPersonNo() {
return personNo;
}
public void setPersonNo(String personNo) {
this.personNo = personNo;
}
@Override
public String toString() {
return "Person [personId=" + personId + ", personNo=" + personNo + ", name=" + name + ", birth=" + birth + ", email=" + email + "]";
}
2、创建DAO
public interface PersonRepository extends JpaRepository<Person,Integer>,QueryByExampleExecutor<Person>{
}
如果只是为了进行QBE查询,继承QueryByExampleExecutor即可,但是一般情况下都会同时继承JpaRepository
3、数据表信息

QBE只是一种查询操作,此处不再讲述表的创建及数据生成等操作。
4、测试
通过QueryByExampleExecutor中的方法可以知道,影响QBE查询的参数主要是Example,而Example的实例有两种方法:static <T> Example<T> of(T probe)和
static <T> Example<T> of(T probe, ExampleMatcher matcher);下面我们将从这两个方面进行测试。
1)、第一种,不好含matcher
测试1
@Autowired
private PersonRepository personRepository;
@Test
public void testQBE() {
Person p = new Person();
p.setName("AA");
Example<Person> example = Example.of(p);
Person person = personRepository.findOne(example).get();
System.out.println(person.toString());
List<Person> list = personRepository.findAll(example);
System.out.println(list.toString());
}
执行结果:

测试2
@Test
public void testQBE2() {
Person p = new Person();
p.setName("AA");
p.setPersonNo("10");
Example<Person> example = Example.of(p);
Person person = personRepository.findOne(example).get();
System.out.println(person.toString());
List<Person> list = personRepository.findAll(example);
System.out.println(list.toString());
}
执行结果:

从执行结果打印的sql可以看出,QBE是根据实体中非空属性进行精确查询。由此可见这是一种精确查询。
2)、第二种,包含matcher
测试1、matching()、matchingAll()
@Test
public void testQBEByMatcher() {
Person p = new Person();
p.setName("aa");
p.setPersonNo("10");
ExampleMatcher matcher = ExampleMatcher.matchingAll();
Example<Person> example = Example.of(p, matcher);
List<Person> list = personRepository.findAll(example);
System.out.println(list.toString());
}
执行结果:

matchingAll()同第一种情况,是以实体非空属性作为查询条件且以and连接的精确查询。
并且从源码可以看出matching()同matchingAll()。
测试2、matchingAny()
@Test
public void testQBEByMatcher2() {
Person p = new Person();
p.setName("aa");
p.setPersonNo("10");
ExampleMatcher matcher = ExampleMatcher.matchingAny();
Example<Person> example = Example.of(p, matcher);
List<Person> list = personRepository.findAll(example);
System.out.println(list.toString());
}
执行结果:

与matchingAll()不同的是此处是以or连接。
测试3、withIgnoreCase()
@Test
public void testQBEByMatcher3() {
Person p = new Person();
p.setName("aa");
p.setPersonNo("10");
ExampleMatcher matcher = ExampleMatcher.matchingAll().withIgnoreCase();
Example<Person> example = Example.of(p, matcher);
List<Person> list = personRepository.findAll(example);
System.out.println(list.toString());
}
执行结果:

从执行结果的sql可以看出这是一种忽略大小写的操作。
测试4、
@Test
public void testQBEByMatcher4() {
Person p = new Person();
p.setName("A");
p.setPersonNo("10");
ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("name", GenericPropertyMatcher.of(StringMatcher.STARTING));
Example<Person> example = Example.of(p, matcher);
List<Person> list = personRepository.findAll(example);
System.out.println(list.toString());
}
执行结果:

从执行结果的sql及参数可以看出,ExampleMatcher.matching().withMatcher("name", GenericPropertyMatcher.of(StringMatcher.STARTING));是指定某属性以XX开头的like查询。
测试5、
@Test
public void testQBEByMatcher5() {
Person p = new Person();
p.setName("A");
p.setPersonNo("10");
ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("name", GenericPropertyMatcher.of(StringMatcher.ENDING));
Example<Person> example = Example.of(p, matcher);
List<Person> list = personRepository.findAll(example);
System.out.println(list.toString());
}
执行结果:

从执行结果的sql及参数可以看出,ExampleMatcher.matching().withMatcher("name", GenericPropertyMatcher.of(StringMatcher.STARTING));是指定某属性以XX开头的like查询。
测试6、
@Test
public void testQBEByMatcher6() {
Person p = new Person();
p.setName("A");
p.setPersonNo("10");
ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("name", GenericPropertyMatcher.of(StringMatcher.CONTAINING));
Example<Person> example = Example.of(p, matcher);
List<Person> list = personRepository.findAll(example);
System.out.println(list.toString());
}
执行结果:

从执行结果的sql及参数可以看出,ExampleMatcher.matching().withMatcher("name", GenericPropertyMatcher.of(StringMatcher.STARTING));是指定某属性包含XX的like查询。
以上仅为本测试的一下场景,其他场景就不一一举例了。
网友评论