Skip to content

Commit 3900401

Browse files
committed
Enable LIKE with SpEL expressions and ESCAPE clause on Hibernate.
The HQL parser has to handle parameters in addition to character values in order to support SpEL. See #2954.
1 parent 2132e7f commit 3900401

File tree

6 files changed

+28
-9
lines changed

6 files changed

+28
-9
lines changed

spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4

+1-1
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ dealingWithNullExpression
554554

555555
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-like-predicate
556556
stringPatternMatching
557-
: expression NOT? (LIKE | ILIKE) expression (ESCAPE character)?
557+
: expression NOT? (LIKE | ILIKE) expression (ESCAPE expression)?
558558
;
559559

560560
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-elements-indices

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1994,7 +1994,7 @@ public List<JpaQueryParsingToken> visitStringPatternMatching(HqlParser.StringPat
19941994
if (ctx.ESCAPE() != null) {
19951995

19961996
tokens.add(new JpaQueryParsingToken(ctx.ESCAPE()));
1997-
tokens.addAll(visit(ctx.character()));
1997+
tokens.addAll(visit(ctx.expression(2)));
19981998
}
19991999

20002000
return tokens;

spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/JpqlQueryRenderer.java

+6
Original file line numberDiff line numberDiff line change
@@ -1206,6 +1206,12 @@ public List<JpaQueryParsingToken> visitLike_expression(JpqlParser.Like_expressio
12061206
tokens.add(new JpaQueryParsingToken(ctx.LIKE()));
12071207
tokens.addAll(visit(ctx.pattern_value()));
12081208

1209+
if (ctx.ESCAPE() != null) {
1210+
1211+
tokens.add(new JpaQueryParsingToken(ctx.ESCAPE()));
1212+
tokens.addAll(visit(ctx.escape_character()));
1213+
}
1214+
12091215
return tokens;
12101216
}
12111217

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/EclipseLinkUserRepositoryFinderTests.java

+18
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,22 @@ void executesNotInQueryCorrectly() {}
3434
@Disabled
3535
@Override
3636
void executesInKeywordForPageCorrectly() {}
37+
38+
@Disabled("Can't get ESCAPE clause working with EclipseLink. See #2955")
39+
@Override
40+
void escapingInLikeSpels() {
41+
super.escapingInLikeSpels();
42+
}
43+
44+
@Disabled("Can't get ESCAPE clause working with EclipseLink. See #2955")
45+
@Override
46+
void escapingInLikeSpelsInThePresenceOfEscapeCharacters() {
47+
super.escapingInLikeSpelsInThePresenceOfEscapeCharacters();
48+
}
49+
50+
@Disabled("Can't get ESCAPE clause working with EclipseLink. See #2955")
51+
@Override
52+
void escapingInLikeSpelsInThePresenceOfEscapedWildcards() {
53+
super.escapingInLikeSpelsInThePresenceOfEscapedWildcards();
54+
}
3755
}

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/UserRepositoryFinderTests.java

+1-6
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
import org.junit.jupiter.api.AfterEach;
2727
import org.junit.jupiter.api.BeforeEach;
28-
import org.junit.jupiter.api.Disabled;
2928
import org.junit.jupiter.api.Test;
3029
import org.junit.jupiter.api.extension.ExtendWith;
3130
import org.springframework.beans.factory.annotation.Autowired;
@@ -235,7 +234,6 @@ void parametersForContainsGetProperlyEscaped() {
235234
.isEmpty();
236235
}
237236

238-
@Disabled("Can't get ESCAPE clause working with Hibernate")
239237
@Test // DATAJPA-1519
240238
void escapingInLikeSpels() {
241239

@@ -246,7 +244,6 @@ void escapingInLikeSpels() {
246244
assertThat(userRepository.findContainingEscaped("att_")).containsExactly(extra);
247245
}
248246

249-
@Disabled("Can't get ESCAPE clause working with Hibernate")
250247
@Test // DATAJPA-1522
251248
void escapingInLikeSpelsInThePresenceOfEscapeCharacters() {
252249

@@ -256,7 +253,6 @@ void escapingInLikeSpelsInThePresenceOfEscapeCharacters() {
256253
assertThat(userRepository.findContainingEscaped("att\\x")).containsExactly(withEscapeCharacter);
257254
}
258255

259-
@Disabled("Can't get ESCAPE clause working with Hibernate")
260256
@Test // DATAJPA-1522
261257
void escapingInLikeSpelsInThePresenceOfEscapedWildcards() {
262258

@@ -288,8 +284,7 @@ void executesQueryWithProjectionContainingReferenceToPluralAttribute() {
288284

289285
List<RolesAndFirstname> rolesAndFirstnameBy = userRepository.findRolesAndFirstnameBy();
290286

291-
assertThat(rolesAndFirstnameBy)
292-
.isNotNull();
287+
assertThat(rolesAndFirstnameBy).isNotNull();
293288

294289
for (RolesAndFirstname rolesAndFirstname : rolesAndFirstnameBy) {
295290
assertThat(rolesAndFirstname.getFirstname()).isNotNull();

spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/sample/UserRepository.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,7 @@ List<User> findUsersByFirstnameForSpELExpressionWithParameterIndexOnlyWithEntity
625625
List<NameOnlyDto> findByNamedQueryWithConstructorExpression();
626626

627627
// DATAJPA-1519
628-
@Query("select u from User u where u.lastname like '%?#{escape([0])}%' escape ?#{escapeCharacter()}")
628+
@Query("select u from User u where u.lastname like %?#{escape([0])}% escape ?#{escapeCharacter()}")
629629
List<User> findContainingEscaped(String namePart);
630630

631631
// DATAJPA-1303

0 commit comments

Comments
 (0)