Skip to content

Commit 97255cf

Browse files
gregturnmp911de
authored andcommitted
Resolve handling of ESCAPE clause with LIKE queries on EclipseLink.
Migrate tests to H2 to verify LIKE with ESCAPE works properly on EclipseLink with Spring Data JPA. Resolves #2955 Original Pull Request: #2956.
1 parent 38ced42 commit 97255cf

File tree

11 files changed

+115
-21
lines changed

11 files changed

+115
-21
lines changed

pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
<eclipselink>3.0.3</eclipselink>
3232
<hibernate>6.2.1.Final</hibernate>
3333
<hsqldb>2.7.1</hsqldb>
34+
<h2>2.1.214</h2>
3435
<jsqlparser>4.5</jsqlparser>
3536
<mysql-connector-java>8.0.31</mysql-connector-java>
3637
<postgresql>42.5.0</postgresql>

spring-data-jpa/pom.xml

+7
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,13 @@
100100
<scope>test</scope>
101101
</dependency>
102102

103+
<dependency>
104+
<groupId>com.h2database</groupId>
105+
<artifactId>h2</artifactId>
106+
<version>${h2}</version>
107+
<scope>test</scope>
108+
</dependency>
109+
103110
<!-- MySQL testing support -->
104111
<dependency>
105112
<groupId>com.mysql</groupId>

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -579,7 +579,7 @@ dealingWithNullExpression
579579

580580
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-like-predicate
581581
stringPatternMatching
582-
: expression NOT? (LIKE | ILIKE) expression (ESCAPE expression)?
582+
: expression NOT? (LIKE | ILIKE) expression (ESCAPE (character|parameter))?
583583
;
584584

585585
// 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

+5-1
Original file line numberDiff line numberDiff line change
@@ -2124,7 +2124,11 @@ public List<JpaQueryParsingToken> visitStringPatternMatching(HqlParser.StringPat
21242124
if (ctx.ESCAPE() != null) {
21252125

21262126
tokens.add(new JpaQueryParsingToken(ctx.ESCAPE()));
2127-
tokens.addAll(visit(ctx.expression(2)));
2127+
if (ctx.character() != null) {
2128+
tokens.addAll(visit(ctx.character()));
2129+
} else if (ctx.parameter() != null) {
2130+
tokens.addAll(visit(ctx.parameter()));
2131+
}
21282132
}
21292133

21302134
return tokens;

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

+2-18
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@
2323
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=349477.
2424
*
2525
* @author Oliver Gierke
26+
* @author Greg Turnquist
2627
*/
27-
@ContextConfiguration("classpath:eclipselink.xml")
28+
@ContextConfiguration("classpath:eclipselink-h2.xml")
2829
class EclipseLinkUserRepositoryFinderTests extends UserRepositoryFinderTests {
2930

3031
@Disabled
@@ -35,21 +36,4 @@ void executesNotInQueryCorrectly() {}
3536
@Override
3637
void executesInKeywordForPageCorrectly() {}
3738

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-
}
5539
}

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

+2-1
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,11 @@
5252
*
5353
* @author Oliver Gierke
5454
* @author Krzysztof Krason
55+
* @author Greg Turnquist
5556
* @see QueryLookupStrategy
5657
*/
5758
@ExtendWith(SpringExtension.class)
58-
@ContextConfiguration(locations = "classpath:config/namespace-application-context.xml")
59+
@ContextConfiguration(locations = "classpath:config/namespace-application-context-h2.xml")
5960
@Transactional
6061
class UserRepositoryFinderTests {
6162

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<beans xmlns="http://www.springframework.org/schema/beans"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
5+
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
6+
http://www.springframework.org/schema/data/jpa https://www.springframework.org/schema/data/jpa/spring-jpa.xsd">
7+
8+
<import resource="../infrastructure-h2.xml"/>
9+
10+
<!--
11+
12+
Simplified DAO configuration:
13+
14+
1. Looks for DAO interfaces in ${dao-config.dao-package-name} named ${dao.name}Dao
15+
2. Uses entity classes from ${dao-config.entity-package-name}
16+
3. Registers daos under ${dao.name}Dao in the applicationContext
17+
4. Add postfix attributes to dao-config element as needed
18+
19+
You can register DAOs as needed by simply adding "dao" elements named after domain classes
20+
and provide an DAO interface named as described above.
21+
22+
! Note, that PersistenceAnnotationBeanPostProcessor and PersistenceExceptionTranslationPostProcessor !
23+
! do not have to be explicitly registered as they are included by namespace parser !
24+
25+
-->
26+
<jpa:repositories base-package="org.springframework.data.jpa.repository.sample"/>
27+
28+
<!-- Register custom DAO implementation explicitly -->
29+
<bean id="userRepositoryImpl" class="org.springframework.data.jpa.repository.sample.UserRepositoryImpl"/>
30+
31+
</beans>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<beans xmlns="http://www.springframework.org/schema/beans"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xmlns:util="http://www.springframework.org/schema/util"
5+
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
6+
http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
7+
8+
<!-- EclipseLink vendor adaptor with workaround platform class for HSQL usage -->
9+
<bean id="vendorAdaptor" class="org.springframework.data.jpa.repository.CustomEclipseLinkJpaVendorAdapter" parent="abstractVendorAdaptor" />
10+
11+
<util:properties id="jpaProperties">
12+
<prop key="jakarta.persistence.jdbc.driver">org.h2.Driver</prop>
13+
<prop key="jakarta.persistence.jdbc.url">jdbc:h2:mem:hades</prop>
14+
<prop key="jakarta.persistence.jdbc.user">sa</prop>
15+
<prop key="jakarta.persistence.jdbc.password"></prop>
16+
<prop key="jakarta.persistence.ddl-generation">create-tables</prop>
17+
<prop key="eclipselink.weaving.internal">false</prop>
18+
<prop key="eclipselink.logging.level">SEVERE</prop>
19+
</util:properties>
20+
21+
</beans>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<beans xmlns="http://www.springframework.org/schema/beans"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
5+
xsi:schemaLocation="http://www.springframework.org/schema/jdbc https://www.springframework.org/schema/jdbc/spring-jdbc.xsd
6+
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
7+
8+
<import resource="hibernate.xml"/>
9+
10+
<bean id="entityManagerFactory"
11+
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
12+
<property name="dataSource" ref="dataSource"/>
13+
<property name="persistenceUnitName" value="spring-data-jpa"/>
14+
<property name="jpaVendorAdapter" ref="vendorAdaptor"/>
15+
<property name="jpaProperties" ref="jpaProperties"/>
16+
</bean>
17+
18+
<bean id="abstractVendorAdaptor" abstract="true">
19+
<property name="generateDdl" value="true"/>
20+
<property name="database" value="H2"/>
21+
</bean>
22+
23+
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
24+
<property name="entityManagerFactory" ref="entityManagerFactory"/>
25+
</bean>
26+
27+
<bean name="sampleEvaluationContextExtension"
28+
class="org.springframework.data.jpa.repository.sample.SampleEvaluationContextExtension"/>
29+
30+
<jdbc:embedded-database id="dataSource" type="H2" generate-name="true">
31+
<jdbc:script execution="INIT" separator="/;" location="classpath:scripts/h2-init.sql"/>
32+
<jdbc:script execution="INIT" separator="/;" location="classpath:scripts/h2-stored-procedures.sql"/>
33+
</jdbc:embedded-database>
34+
35+
</beans>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/;
2+
DROP alias IF EXISTS plus1inout
3+
/;
4+
CREATE alias plus1inout AS $$
5+
Integer plus1inout(Integer arg) {
6+
return arg + 1;
7+
}
8+
$$
9+
/;

0 commit comments

Comments
 (0)