|
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 domain object object or a subtype of it) and a specification how to match properties. You can use Query by Example with the `MongoTemplate` and 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 domain objects 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 |
| -public class Person { |
36 |
| -
|
37 |
| - @Id |
38 |
| - private String id; |
39 |
| - private String firstname; |
40 |
| - private String lastname; |
41 |
| - private Address address; |
42 |
| -
|
43 |
| - // … getters and setters omitted |
44 |
| -} |
45 |
| ----- |
46 |
| -==== |
47 |
| - |
48 |
| -This is a simple domain object. 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. |
49 |
| - |
50 |
| -.Simple Example specification |
51 |
| -==== |
52 |
| -[source,xml] |
53 |
| ----- |
54 |
| -Person person = new Person(); <1> |
55 |
| -
|
56 |
| -person.setFirstname("Dave"); <2> |
57 |
| -
|
58 |
| -Example<Person> example = Example.exampleOf(person); <3> |
59 |
| ----- |
60 |
| -<1> Create a new instance of the domain object |
61 |
| -<2> Set the properties to query |
62 |
| -<3> Create an `Example` |
63 |
| -==== |
64 |
| - |
65 |
| - |
66 |
| -NOTE: Property names of the sample object must correlate with the property names of the queried domain object. |
| 4 | +In Spring Data MongoDB you can use Query by Example with the `MongoTemplate` and with Repositories. |
67 | 5 |
|
68 | 6 | .Query by Example using MongoTemplate
|
69 | 7 | ====
|
70 | 8 | [source,xml]
|
71 | 9 | ----
|
72 |
| -@Autowired |
73 |
| -MongoTemplate template; |
| 10 | +public class PersonService { |
| 11 | + @Autowired MongoTemplate template; |
74 | 12 |
|
75 |
| -public List<Person> findPeople(Person sampleObject) { |
76 |
| - return template.findByExample(Example.exampleOf(person)); |
| 13 | + public List<Person> findPeople(Person probe) { |
| 14 | + return template.findByExample(Example.of(probe)); |
| 15 | + } |
77 | 16 | }
|
78 | 17 | ----
|
79 | 18 | ====
|
80 | 19 |
|
81 |
| -`MongoTemplate.findByExample` accepts either the sample object or an `Example` object to create and execute a query. |
| 20 | +`MongoTemplate.findByExample` accepts either the probe or an `Example` object to create and execute a query. |
82 | 21 |
|
83 | 22 |
|
84 | 23 | .Query by Example using a Repository
|
85 | 24 | ====
|
86 | 25 | [source, java]
|
87 | 26 | ----
|
88 |
| -public interface MongoRepository<Person, String> { |
| 27 | +public interface PersonRepository extends MongoRepository<Person, String> { |
89 | 28 |
|
90 |
| - <S extends Person> List<Person> findAllByExample(Example<S> example); |
| 29 | +} |
91 | 30 |
|
92 |
| - <S extends Person> List<Person> findAllByExample(Example<S> example, Sort sort); |
| 31 | +public class PersonService { |
93 | 32 |
|
94 |
| - <S extends Person> Page<Person> findAllByExample(Example<S> example, Pageable pageable); |
| 33 | + @Autowired PersonRepository personRepository; |
95 | 34 |
|
96 |
| - // … more functionality omitted. |
| 35 | + public List<Person> findPeople(Person probe) { |
| 36 | + return personRepository.findAll(Example.of(probe)); |
| 37 | + } |
97 | 38 | }
|
98 | 39 | ----
|
99 | 40 | ====
|
100 | 41 |
|
101 |
| -[[query.by.example.builder]] |
102 |
| -== Example builder |
103 |
| - |
104 |
| -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. |
105 |
| - |
106 |
| -.Query by Example builder |
107 |
| -==== |
108 |
| -[source, java] |
109 |
| ----- |
110 |
| -Example.newExampleOf(person) |
111 |
| - .withStringMatcher(StringMatcher.ENDING) |
112 |
| - .includeNullValues() |
113 |
| - .withPropertySpecifier( |
114 |
| - newPropertySpecifier("firstname").matchString(StringMatcher.CONTAINING).get()) |
115 |
| - .withPropertySpecifier( |
116 |
| - newPropertySpecifier("lastname").matchStringsWithIgnoreCase().get()) |
117 |
| - .withPropertySpecifier( |
118 |
| - newPropertySpecifier("address.city").matchStringStartingWith().get()) |
119 |
| - .get(); |
120 |
| ----- |
121 |
| -==== |
| 42 | +NOTE: When including `null` values in the `ExampleSpec` Spring Data Mongo uses embedded document matching instead of dot notation property matching. This forces exact document matching for all property values and the property order in the embedded document. |
122 | 43 |
|
123 |
| -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. |
| 44 | +Spring Data MongoDB provides support for the following matching options: |
124 | 45 |
|
125 | 46 | [cols="1,2", options="header"]
|
126 | 47 | .`StringMatcher` options
|
|
0 commit comments