Skip to content

Commit

Permalink
DATAJPA-292 - Manually defined queries can contain like expressions now.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
odrotbohm committed Mar 13, 2013
1 parent c2aa121 commit 285a994
Show file tree
Hide file tree
Showing 8 changed files with 701 additions and 12 deletions.
25 changes: 25 additions & 0 deletions src/docbkx/jpa.xml
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,31 @@ public class User {
}</programlisting>
</example>

<simplesect>
<title>Using advanced <code>LIKE</code> expressions</title>

<para>The query execution mechanism for manually defined queries using
<interfacename>@Query</interfacename> allow the definition of advanced
<code>LIKE</code> expressions inside the query definition.</para>

<example>
<title>Advanced <code>LIKE</code> expressions in
<interfacename>@Query</interfacename></title>

<programlisting language="java">public interface UserRepository extends JpaRepository&lt;User, Long&gt; {

@Query("select u from User u where u.firstname like %?1")
List&lt;User&gt; findByFirstnameEndsWith(String firstname);
}</programlisting>
</example>

<para>In the just shown sample <code>LIKE</code> delimiter character
<code>%</code> is recognized and the query transformed into a valid
JPQL query (removing the <code>%</code>). Upon query execution the
parameter handed into the method call gets augmented with the
previously recognized <code>LIKE</code> pattern.</para>
</simplesect>

<simplesect>
<title>Native queries</title>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ final class SimpleJpaQuery extends AbstractJpaQuery {

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

private final String queryString;
private final String countQuery;
private final String alias;
private final StringQuery query;
private final StringQuery countQuery;

private final JpaQueryMethod method;

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

super(method, em);

this.queryString = queryString;
this.alias = QueryUtils.detectAlias(queryString);
this.countQuery = method.getCountQuery() == null ? QueryUtils.createCountQueryFor(queryString) : method
.getCountQuery();
this.method = method;
this.query = new StringQuery(queryString);
this.countQuery = new StringQuery(method.getCountQuery() == null ? QueryUtils.createCountQueryFor(queryString)
: method.getCountQuery());

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

/*
* (non-Javadoc)
* @see org.springframework.data.jpa.repository.query.AbstractJpaQuery#createBinder(java.lang.Object[])
*/
@Override
protected ParameterBinder createBinder(Object[] values) {
return new StringQueryParameterBinder(getQueryMethod().getParameters(), values, query);
}

/*
* (non-Javadoc)
* @see org.springframework.data.jpa.repository.query.AbstractJpaQuery#createQuery(java.lang.Object[])
Expand All @@ -90,7 +97,7 @@ final class SimpleJpaQuery extends AbstractJpaQuery {
public Query doCreateQuery(Object[] values) {

ParameterAccessor accessor = new ParametersParameterAccessor(method.getParameters(), values);
String sortedQueryString = QueryUtils.applySorting(queryString, accessor.getSort(), alias);
String sortedQueryString = QueryUtils.applySorting(query.getQuery(), accessor.getSort(), query.getAlias());
EntityManager em = getEntityManager();

Query query = null;
Expand All @@ -111,8 +118,7 @@ public Query doCreateQuery(Object[] values) {
*/
@Override
protected TypedQuery<Long> doCreateCountQuery(Object[] values) {

return createBinder(values).bind(getEntityManager().createQuery(countQuery, Long.class));
return createBinder(values).bind(getEntityManager().createQuery(countQuery.getQuery(), Long.class));
}

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

return query == null ? null : new SimpleJpaQuery(queryMethod, em, query);
}
}
}
Loading

0 comments on commit 285a994

Please sign in to comment.