34
34
35
35
import org .springframework .dao .InvalidDataAccessApiUsageException ;
36
36
import org .springframework .data .domain .Example ;
37
- import org .springframework .data .domain .Example .NullHandler ;
37
+ import org .springframework .data .domain .ExampleSpec ;
38
+ import org .springframework .data .domain .ExampleSpecAccessor ;
38
39
import org .springframework .data .util .DirectFieldAccessFallbackBeanWrapper ;
39
40
import org .springframework .orm .jpa .JpaSystemException ;
40
41
import org .springframework .util .Assert ;
48
49
* The builder includes any {@link SingularAttribute} of the {@link Example#getProbe()} applying {@link String} and
49
50
* {@literal null} matching strategies configured on the {@link Example}. Ignored paths are no matter of their actual
50
51
* value not considered. <br />
51
- *
52
+ *
52
53
* @author Christoph Strobl
54
+ * @author Mark Paluch
53
55
* @since 1.10
54
56
*/
55
57
public class QueryByExamplePredicateBuilder {
@@ -63,7 +65,7 @@ public class QueryByExamplePredicateBuilder {
63
65
64
66
/**
65
67
* Extract the {@link Predicate} representing the {@link Example}.
66
- *
68
+ *
67
69
* @param root must not be {@literal null}.
68
70
* @param cb must not be {@literal null}.
69
71
* @param example must not be {@literal null}.
@@ -73,10 +75,10 @@ public static <T> Predicate getPredicate(Root<T> root, CriteriaBuilder cb, Examp
73
75
74
76
Assert .notNull (root , "Root must not be null!" );
75
77
Assert .notNull (cb , "CriteriaBuilder must not be null!" );
76
- Assert .notNull (example , "Root must not be null!" );
78
+ Assert .notNull (example , "Example must not be null!" );
77
79
78
- List <Predicate > predicates = getPredicates ("" , cb , root , root .getModel (), example .getSampleObject (), example ,
79
- new PathNode ("root" , null , example .getSampleObject ()));
80
+ List <Predicate > predicates = getPredicates ("" , cb , root , root .getModel (), example .getProbe () ,
81
+ example . getProbeType (), ExampleSpecAccessor . of ( example ), new PathNode ("root" , null , example .getProbe ()));
80
82
81
83
if (predicates .isEmpty ()) {
82
84
return cb .isTrue (cb .literal (false ));
@@ -90,8 +92,8 @@ public static <T> Predicate getPredicate(Root<T> root, CriteriaBuilder cb, Examp
90
92
}
91
93
92
94
@ SuppressWarnings ({ "rawtypes" , "unchecked" })
93
- static List <Predicate > getPredicates (String path , CriteriaBuilder cb , Path <?> from , ManagedType <?> type ,
94
- Object value , Example <?> example , PathNode currentNode ) {
95
+ static List <Predicate > getPredicates (String path , CriteriaBuilder cb , Path <?> from , ManagedType <?> type , Object value ,
96
+ Class <?> probeType , ExampleSpecAccessor exampleAccessor , PathNode currentNode ) {
95
97
96
98
List <Predicate > predicates = new ArrayList <Predicate >();
97
99
DirectFieldAccessFallbackBeanWrapper beanWrapper = new DirectFieldAccessFallbackBeanWrapper (value );
@@ -100,16 +102,16 @@ static List<Predicate> getPredicates(String path, CriteriaBuilder cb, Path<?> fr
100
102
101
103
String currentPath = !StringUtils .hasText (path ) ? attribute .getName () : path + "." + attribute .getName ();
102
104
103
- if (example .isIgnoredPath (currentPath )) {
105
+ if (exampleAccessor .isIgnoredPath (currentPath )) {
104
106
continue ;
105
107
}
106
108
107
- Object attributeValue = example .getValueTransformerForPath (currentPath ). convert (
108
- beanWrapper .getPropertyValue (attribute .getName ()));
109
+ Object attributeValue = exampleAccessor .getValueTransformerForPath (currentPath )
110
+ . convert ( beanWrapper .getPropertyValue (attribute .getName ()));
109
111
110
112
if (attributeValue == null ) {
111
113
112
- if (example .getNullHandler ().equals (NullHandler .INCLUDE )) {
114
+ if (exampleAccessor .getNullHandler ().equals (ExampleSpec . NullHandler .INCLUDE )) {
113
115
predicates .add (cb .isNull (from .get (attribute )));
114
116
}
115
117
continue ;
@@ -118,39 +120,39 @@ static List<Predicate> getPredicates(String path, CriteriaBuilder cb, Path<?> fr
118
120
if (attribute .getPersistentAttributeType ().equals (PersistentAttributeType .EMBEDDED )) {
119
121
120
122
predicates .addAll (getPredicates (currentPath , cb , from .get (attribute .getName ()),
121
- (ManagedType <?>) attribute .getType (), attributeValue , example , currentNode ));
123
+ (ManagedType <?>) attribute .getType (), attributeValue , probeType , exampleAccessor , currentNode ));
122
124
continue ;
123
125
}
124
126
125
127
if (isAssociation (attribute )) {
126
128
127
129
if (!(from instanceof From )) {
128
- throw new JpaSystemException (new IllegalArgumentException (String . format (
129
- "Unexpected path type for %s. Found % where From.class was expected." , currentPath , from )));
130
+ throw new JpaSystemException (new IllegalArgumentException (
131
+ String . format ( "Unexpected path type for %s. Found % where From.class was expected." , currentPath , from )));
130
132
}
131
133
132
134
PathNode node = currentNode .add (attribute .getName (), attributeValue );
133
135
if (node .spansCycle ()) {
134
- throw new InvalidDataAccessApiUsageException (String . format (
135
- "Path '%s' from root %s must not span a cyclic property reference!\r \n %s" , currentPath ,
136
- ClassUtils .getShortName (example . getSampleType () ), node ));
136
+ throw new InvalidDataAccessApiUsageException (
137
+ String . format ( "Path '%s' from root %s must not span a cyclic property reference!\r \n %s" , currentPath ,
138
+ ClassUtils .getShortName (probeType ), node ));
137
139
}
138
140
139
141
predicates .addAll (getPredicates (currentPath , cb , ((From <?, ?>) from ).join (attribute .getName ()),
140
- (ManagedType <?>) attribute .getType (), attributeValue , example , node ));
142
+ (ManagedType <?>) attribute .getType (), attributeValue , probeType , exampleAccessor , node ));
141
143
142
144
continue ;
143
145
}
144
146
145
147
if (attribute .getJavaType ().equals (String .class )) {
146
148
147
149
Expression <String > expression = from .get (attribute );
148
- if (example .isIgnoreCaseForPath (currentPath )) {
150
+ if (exampleAccessor .isIgnoreCaseForPath (currentPath )) {
149
151
expression = cb .lower (expression );
150
152
attributeValue = attributeValue .toString ().toLowerCase ();
151
153
}
152
154
153
- switch (example .getStringMatcherForPath (currentPath )) {
155
+ switch (exampleAccessor .getStringMatcherForPath (currentPath )) {
154
156
155
157
case DEFAULT :
156
158
case EXACT :
@@ -166,8 +168,8 @@ static List<Predicate> getPredicates(String path, CriteriaBuilder cb, Path<?> fr
166
168
predicates .add (cb .like (expression , "%" + attributeValue ));
167
169
break ;
168
170
default :
169
- throw new IllegalArgumentException ("Unsupported StringMatcher "
170
- + example .getStringMatcherForPath (currentPath ));
171
+ throw new IllegalArgumentException (
172
+ "Unsupported StringMatcher " + exampleAccessor .getStringMatcherForPath (currentPath ));
171
173
}
172
174
} else {
173
175
predicates .add (cb .equal (from .get (attribute ), attributeValue ));
@@ -184,7 +186,7 @@ private static boolean isAssociation(Attribute<?, ?> attribute) {
184
186
/**
185
187
* {@link PathNode} is used to dynamically grow a directed graph structure that allows to detect cycles within its
186
188
* direct predecessor nodes by comparing parent node values using {@link System#identityHashCode(Object)}.
187
- *
189
+ *
188
190
* @author Christoph Strobl
189
191
*/
190
192
private static class PathNode {
0 commit comments