DATAJPA-54 - Added forCounting() flag to @QueryHints.
The flag defaults to true and allows disabling of QueryHints being applied to the count query additionally triggered for pagination.
This commit is contained in:
@@ -18,8 +18,8 @@
|
||||
<para>The JPA module of Spring Data contains a custom namespace that
|
||||
allows defining repository beans. It also contains certain features and
|
||||
element attributes that are special to JPA. Generally the JPA
|
||||
repositories can be set up using the <code>repositories</code> element:
|
||||
</para>
|
||||
repositories can be set up using the <code>repositories</code>
|
||||
element:</para>
|
||||
|
||||
<example>
|
||||
<title>Setting up JPA repositories using the namespace</title>
|
||||
@@ -444,6 +444,33 @@ int setFixedFirstnameFor(String firstname, String lastname);</programlisting>
|
||||
<code>clearAutomatically</code> attribute to
|
||||
<literal>false</literal>;</para>
|
||||
</section>
|
||||
|
||||
<section id="jpa.query-hints">
|
||||
<title>Applying query hints</title>
|
||||
|
||||
<para>To apply JPA <interfacename>QueryHint</interfacename>s to the
|
||||
queries declared in your repository interface you can use the
|
||||
<interfacename>QueryHints</interfacename> annotation. It takes an array
|
||||
of JPA <interfacename>QueryHint</interfacename> annotations plus a
|
||||
boolean flag to potentially disable the hints applied to the addtional
|
||||
count query triggered when applying pagination.</para>
|
||||
|
||||
<example>
|
||||
<title>Using QueryHints with a repository method</title>
|
||||
|
||||
<programlisting language="java">public interface UserRepository extends Repository<User, Long> {
|
||||
|
||||
@QueryHints(value = { @QueryHint(name = "name", value = "value")},
|
||||
forCounting = false)
|
||||
Page<User> findByLastname(String lastname, Pageable pageable);
|
||||
}</programlisting>
|
||||
|
||||
<para>The just shown declaration would apply the configured
|
||||
<interfacename>QueryHint</interfacename> for that actually query but
|
||||
omit applying it to the count query triggered to calculate the total
|
||||
number of pages.</para>
|
||||
</example>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id="specifications">
|
||||
|
||||
@@ -34,5 +34,18 @@ import javax.persistence.QueryHint;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface QueryHints {
|
||||
|
||||
/**
|
||||
* The {@link QueryHint}s to apply when the query will be executed.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
QueryHint[] value() default {};
|
||||
|
||||
/**
|
||||
* Defines whether the configured {@link QueryHint}s shall be applied for count queries during pagination as well.
|
||||
* Defaults to {@literal true}.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean forCounting() default true;
|
||||
}
|
||||
|
||||
@@ -131,7 +131,8 @@ public abstract class AbstractJpaQuery implements RepositoryQuery {
|
||||
}
|
||||
|
||||
protected TypedQuery<Long> createCountQuery(Object[] values) {
|
||||
return applyHints(doCreateCountQuery(values), method);
|
||||
TypedQuery<Long> countQuery = doCreateCountQuery(values);
|
||||
return method.applyHintsToCountQuery() ? applyHints(countQuery, method) : countQuery;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -93,6 +93,18 @@ public class JpaQueryMethod extends QueryMethod {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the potentially configured {@link QueryHint}s shall be applied when triggering the count query for
|
||||
* pagination.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
boolean applyHintsToCountQuery() {
|
||||
|
||||
QueryHints hints = getAnnotation(method, QueryHints.class);
|
||||
return hints != null ? hints.forCounting() : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link QueryExtractor}.
|
||||
*
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2008-2011 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.jpa.repository.query;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
@@ -65,10 +80,34 @@ public class AbstractJpaQueryTests {
|
||||
verify(result).setHint("foo", "bar");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAJPA-54
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void skipsHintsForCountQueryIfConfigured() throws Exception {
|
||||
|
||||
Method method = SampleRepository.class.getMethod("findByFirstname", String.class);
|
||||
QueryExtractor provider = PersistenceProvider.fromEntityManager(em);
|
||||
JpaQueryMethod queryMethod = new JpaQueryMethod(method, new DefaultRepositoryMetadata(SampleRepository.class),
|
||||
provider);
|
||||
|
||||
AbstractJpaQuery jpaQuery = new DummyJpaQuery(queryMethod, em);
|
||||
|
||||
Query result = jpaQuery.createQuery(new Object[] { "Dave" });
|
||||
verify(result).setHint("bar", "foo");
|
||||
|
||||
result = jpaQuery.createCountQuery(new Object[] { "Dave" });
|
||||
verify(result, never()).setHint("bar", "foo");
|
||||
}
|
||||
|
||||
interface SampleRepository extends Repository<User, Integer> {
|
||||
|
||||
@QueryHints({ @QueryHint(name = "foo", value = "bar") })
|
||||
List<User> findByLastname(String lastname);
|
||||
|
||||
@QueryHints(value = { @QueryHint(name = "bar", value = "foo") }, forCounting = false)
|
||||
List<User> findByFirstname(String firstname);
|
||||
}
|
||||
|
||||
class DummyJpaQuery extends AbstractJpaQuery {
|
||||
|
||||
Reference in New Issue
Block a user