|
1 |
| -[[query.by.example]] |
2 |
| -= Query by Example |
| 1 | +[[query.by.example.execution]] |
| 2 | +== Executing Query by Example |
3 | 3 |
|
4 |
| -== Introduction |
5 |
| - |
6 |
| -This chapter will give you an introduction to Query by Example and explain how to use example specifications. |
7 |
| - |
8 |
| -Query by Example (QBE) is a user-friendly querying technique with a simple interface. It allows dynamic query creation and does not require to write queries containing field names. In fact, Query by Example does not require to write queries using store-specific query languages at all. |
9 |
| - |
10 |
| -== Usage |
11 |
| - |
12 |
| -An `Example` takes a data object (usually the entity object or a subtype of it) and a specification how to match properties. You can use Query by Example with Repositories. |
13 |
| - |
14 |
| -Query by Example is suited for several use-cases but also comes with limitations: |
15 |
| - |
16 |
| -**When to use** |
17 |
| - |
18 |
| -* Querying your data store with a set of static or dynamic constraints |
19 |
| -* Frequent refactoring of the entities without worrying about breaking existing queries |
20 |
| -* Works independently from the data store API |
21 |
| - |
22 |
| -**Limitations** |
23 |
| - |
24 |
| -* Query predicates are combined using the `AND` keyword |
25 |
| -* No support for nested/grouped property constraints like `firstname = ?0 or (firstname = ?1 and lastname = ?2)` |
26 |
| -* Only supports starts/contains/ends/regex matching for strings and exact matching for other property types |
27 |
| - |
28 |
| - |
29 |
| -Before getting started with Query by Example you need to have your interface to the data store set up. |
30 |
| - |
31 |
| -.Sample Person object |
32 |
| -==== |
33 |
| -[source,java] |
34 |
| ----- |
35 |
| -@Entity |
36 |
| -public class Person { |
37 |
| -
|
38 |
| - @Id |
39 |
| - private String id; |
40 |
| - private String firstname; |
41 |
| - private String lastname; |
42 |
| - private Address address; |
43 |
| -
|
44 |
| - // … getters and setters omitted |
45 |
| -} |
46 |
| ----- |
47 |
| -==== |
48 |
| - |
49 |
| -This is a simple entity. You can use it to create an Example specification. By default, fields having `null` values are ignored, and strings are matched using the store specific defaults. Examples can be built by either using the `exampleOf` factory method or by using the <<query.by.example.builder,Example builder>>. Once the `Example` is constructed it becomes immutable. |
50 |
| - |
51 |
| -.Simple Example specification |
52 |
| -==== |
53 |
| -[source,xml] |
54 |
| ----- |
55 |
| -Person person = new Person(); <1> |
56 |
| -
|
57 |
| -person.setFirstname("Dave"); <2> |
58 |
| -
|
59 |
| -Example<Person> example = Example.exampleOf(person); <3> |
60 |
| ----- |
61 |
| -<1> Create a new instance of the entity |
62 |
| -<2> Set the properties to query |
63 |
| -<3> Create an `Example` |
64 |
| -==== |
65 |
| - |
66 |
| - |
67 |
| -NOTE: Property names of the sample object must correlate with the property names of the queried entity. |
| 4 | +In Spring Data JPA you can use Query by Example with Repositories. |
68 | 5 |
|
69 | 6 | .Query by Example using a Repository
|
70 | 7 | ====
|
71 | 8 | [source, java]
|
72 | 9 | ----
|
73 |
| -public interface JpaRepository<Person, String> { |
| 10 | +public interface PersonRepository extends JpaRepository<Person, String> { |
74 | 11 |
|
75 |
| - List<Person> findAllByExample(Example<Person> example); |
| 12 | +} |
76 | 13 |
|
77 |
| - List<Person> findAllByExample(Example<Person> example, Sort sort); |
| 14 | +public class PersonService { |
78 | 15 |
|
79 |
| - Page<Person> findAllByExample(Example<Person> example, Pageable pageable); |
| 16 | + @Autowired PersonRepository personRepository; |
80 | 17 |
|
81 |
| - // … more functionality omitted. |
| 18 | + public List<Person> findPeople(Person probe) { |
| 19 | + return personRepository.findAll(Example.of(probe)); |
| 20 | + } |
82 | 21 | }
|
83 | 22 | ----
|
84 | 23 | ====
|
85 | 24 |
|
86 |
| -[[query.by.example.builder]] |
87 |
| -== Example builder |
| 25 | +NOTE: Only SingularAttribute properties can be used for property matching. |
88 | 26 |
|
89 |
| -Examples are not limited to default settings. You can specify own defaults for string matching, null handling and property-specific settings using the example builder. |
90 |
| - |
91 |
| -.Query by Example builder |
92 |
| -==== |
93 |
| -[source, java] |
94 |
| ----- |
95 |
| -Example.newExampleOf(person) |
96 |
| - .withStringMatcher(StringMatcher.ENDING) |
97 |
| - .includeNullValues() |
98 |
| - .withPropertySpecifier( |
99 |
| - newPropertySpecifier("firstname").matchString(StringMatcher.CONTAINING).get()) |
100 |
| - .withPropertySpecifier( |
101 |
| - newPropertySpecifier("lastname").matchStringsWithIgnoreCase().get()) |
102 |
| - .withPropertySpecifier( |
103 |
| - newPropertySpecifier("address.city").matchStringStartingWith().get()) |
104 |
| - .get(); |
105 |
| ----- |
106 |
| -==== |
107 | 27 |
|
108 | 28 | Property specifier accepts property names (e.g. "firstname" and "lastname"). You can navigate by chaining properties together with dots ("address.city"). You can tune it with matching options and case sensitivity.
|
109 | 29 |
|
|
0 commit comments