Skip to content

Commit 285a994

Browse files
committed
DATAJPA-292 - Manually defined queries can contain like expressions now.
This commit introduces support for JPQL inline like expressions such as "… like ?1%". The implementation will detect those expressions and turn the query back into a valid JPQL one. On query execution the parameters will be bound according to the like expression defined in the query.
1 parent c2aa121 commit 285a994

File tree

8 files changed

+701
-12
lines changed

8 files changed

+701
-12
lines changed

Diff for: src/docbkx/jpa.xml

+25
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,31 @@ public class User {
508508
}</programlisting>
509509
</example>
510510

511+
<simplesect>
512+
<title>Using advanced <code>LIKE</code> expressions</title>
513+
514+
<para>The query execution mechanism for manually defined queries using
515+
<interfacename>@Query</interfacename> allow the definition of advanced
516+
<code>LIKE</code> expressions inside the query definition.</para>
517+
518+
<example>
519+
<title>Advanced <code>LIKE</code> expressions in
520+
<interfacename>@Query</interfacename></title>
521+
522+
<programlisting language="java">public interface UserRepository extends JpaRepository&lt;User, Long&gt; {
523+
524+
@Query("select u from User u where u.firstname like %?1")
525+
List&lt;User&gt; findByFirstnameEndsWith(String firstname);
526+
}</programlisting>
527+
</example>
528+
529+
<para>In the just shown sample <code>LIKE</code> delimiter character
530+
<code>%</code> is recognized and the query transformed into a valid
531+
JPQL query (removing the <code>%</code>). Upon query execution the
532+
parameter handed into the method call gets augmented with the
533+
previously recognized <code>LIKE</code> pattern.</para>
534+
</simplesect>
535+
511536
<simplesect>
512537
<title>Native queries</title>
513538

Diff for: src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java

+18-12
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,8 @@ final class SimpleJpaQuery extends AbstractJpaQuery {
3737

3838
private static final Logger LOG = LoggerFactory.getLogger(SimpleJpaQuery.class);
3939

40-
private final String queryString;
41-
private final String countQuery;
42-
private final String alias;
40+
private final StringQuery query;
41+
private final StringQuery countQuery;
4342

4443
private final JpaQueryMethod method;
4544

@@ -50,11 +49,10 @@ final class SimpleJpaQuery extends AbstractJpaQuery {
5049

5150
super(method, em);
5251

53-
this.queryString = queryString;
54-
this.alias = QueryUtils.detectAlias(queryString);
55-
this.countQuery = method.getCountQuery() == null ? QueryUtils.createCountQueryFor(queryString) : method
56-
.getCountQuery();
5752
this.method = method;
53+
this.query = new StringQuery(queryString);
54+
this.countQuery = new StringQuery(method.getCountQuery() == null ? QueryUtils.createCountQueryFor(queryString)
55+
: method.getCountQuery());
5856

5957
Parameters parameters = method.getParameters();
6058
boolean hasPagingOrSortingParameter = parameters.hasPageableParameter() || parameters.hasSortParameter();
@@ -66,7 +64,7 @@ final class SimpleJpaQuery extends AbstractJpaQuery {
6664
// Try to create a Query object already to fail fast
6765
if (!method.isNativeQuery()) {
6866
try {
69-
em.createQuery(queryString);
67+
em.createQuery(query.getQuery());
7068
} catch (RuntimeException e) {
7169
// Needed as there's ambiguities in how an invalid query string shall be expressed by the persistence provider
7270
// http://java.net/projects/jpa-spec/lists/jsr338-experts/archive/2012-07/message/17
@@ -82,6 +80,15 @@ final class SimpleJpaQuery extends AbstractJpaQuery {
8280
this(method, em, method.getAnnotatedQuery());
8381
}
8482

83+
/*
84+
* (non-Javadoc)
85+
* @see org.springframework.data.jpa.repository.query.AbstractJpaQuery#createBinder(java.lang.Object[])
86+
*/
87+
@Override
88+
protected ParameterBinder createBinder(Object[] values) {
89+
return new StringQueryParameterBinder(getQueryMethod().getParameters(), values, query);
90+
}
91+
8592
/*
8693
* (non-Javadoc)
8794
* @see org.springframework.data.jpa.repository.query.AbstractJpaQuery#createQuery(java.lang.Object[])
@@ -90,7 +97,7 @@ final class SimpleJpaQuery extends AbstractJpaQuery {
9097
public Query doCreateQuery(Object[] values) {
9198

9299
ParameterAccessor accessor = new ParametersParameterAccessor(method.getParameters(), values);
93-
String sortedQueryString = QueryUtils.applySorting(queryString, accessor.getSort(), alias);
100+
String sortedQueryString = QueryUtils.applySorting(query.getQuery(), accessor.getSort(), query.getAlias());
94101
EntityManager em = getEntityManager();
95102

96103
Query query = null;
@@ -111,8 +118,7 @@ public Query doCreateQuery(Object[] values) {
111118
*/
112119
@Override
113120
protected TypedQuery<Long> doCreateCountQuery(Object[] values) {
114-
115-
return createBinder(values).bind(getEntityManager().createQuery(countQuery, Long.class));
121+
return createBinder(values).bind(getEntityManager().createQuery(countQuery.getQuery(), Long.class));
116122
}
117123

118124
/**
@@ -131,4 +137,4 @@ public static RepositoryQuery fromQueryAnnotation(JpaQueryMethod queryMethod, En
131137

132138
return query == null ? null : new SimpleJpaQuery(queryMethod, em, query);
133139
}
134-
}
140+
}

0 commit comments

Comments
 (0)