2929 * <p>
3030 * Each restriction pairs an {@linkplain SingularAttribute attribute} of the
3131 * entity with a {@link Range} of allowed values for the attribute.
32+ * <p>
33+ * A parameter of a {@linkplain org.hibernate.annotations.processing.Find
34+ * finder method} or {@linkplain org.hibernate.annotations.processing.HQL
35+ * HQL query method} may be declared with type {@code Restriction<? super E>},
36+ * {@code List<Restriction<? super E>>}, or {@code Restriction<? super E>...}
37+ * (varargs) where {@code E} is the entity type returned by the query.
3238 *
3339 * @param <X> The entity result type of the query
3440 *
@@ -163,19 +169,35 @@ static <T> Restriction<T> notLike(SingularAttribute<T, String> attribute, String
163169 }
164170
165171 static <T > Restriction <T > startsWith (SingularAttribute <T , String > attribute , String prefix ) {
166- return like ( attribute , escape ( prefix ) + '%' );
172+ return startsWith ( attribute , prefix , true );
167173 }
168174
169- static <T > Restriction <T > endWith (SingularAttribute <T , String > attribute , String suffix ) {
170- return like ( attribute , '%' + escape ( suffix ) );
175+ static <T > Restriction <T > endsWith (SingularAttribute <T , String > attribute , String suffix ) {
176+ return endsWith ( attribute , suffix , true );
171177 }
172178
173179 static <T > Restriction <T > contains (SingularAttribute <T , String > attribute , String substring ) {
174- return like ( attribute , '%' + escape ( substring ) + '%' );
180+ return contains ( attribute , substring , true );
175181 }
176182
177183 static <T > Restriction <T > notContains (SingularAttribute <T , String > attribute , String substring ) {
178- return contains ( attribute , substring ).negated ();
184+ return notContains ( attribute , substring , true );
185+ }
186+
187+ static <T > Restriction <T > startsWith (SingularAttribute <T , String > attribute , String prefix , boolean caseSensitive ) {
188+ return restrict ( attribute , Range .prefix ( prefix , caseSensitive ) );
189+ }
190+
191+ static <T > Restriction <T > endsWith (SingularAttribute <T , String > attribute , String suffix , boolean caseSensitive ) {
192+ return restrict ( attribute , Range .suffix ( suffix , caseSensitive ) );
193+ }
194+
195+ static <T > Restriction <T > contains (SingularAttribute <T , String > attribute , String substring , boolean caseSensitive ) {
196+ return restrict ( attribute , Range .containing ( substring , caseSensitive ) );
197+ }
198+
199+ static <T > Restriction <T > notContains (SingularAttribute <T , String > attribute , String substring , boolean caseSensitive ) {
200+ return contains ( attribute , substring , caseSensitive ).negated ();
179201 }
180202
181203 static <T > Restriction <T > all (List <? extends Restriction <? super T >> restrictions ) {
@@ -199,16 +221,4 @@ static <T> Restriction<T> any(Restriction<? super T>... restrictions) {
199221 static <T > Restriction <T > unrestricted () {
200222 return new Unrestricted <>();
201223 }
202-
203- private static String escape (String literal ) {
204- final var result = new StringBuilder ();
205- for ( int i = 0 ; i < literal .length (); i ++ ) {
206- final char ch = literal .charAt ( i );
207- if ( ch =='%' || ch =='_' || ch =='\\' ) {
208- result .append ('\\' );
209- }
210- result .append ( ch );
211- }
212- return result .toString ();
213- }
214224}
0 commit comments