diff --git a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java index 35dc82cc9..263aba161 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java @@ -67,11 +67,6 @@ public class JpaQueryMethod extends QueryMethod { Assert.isTrue(!(isModifyingQuery() && getParameters() .hasSpecialParameter()), String.format( "Modifying method must not contain %s!", Parameters.TYPES)); - - Assert.isTrue(!(getParameters().hasPageableParameter() && !extractor - .canExtractQuery()), - "You cannot use Pageable as method parameter if your " - + "persistence provider cannot extract queries!"); } diff --git a/src/main/java/org/springframework/data/jpa/repository/query/NamedQuery.java b/src/main/java/org/springframework/data/jpa/repository/query/NamedQuery.java index c2f49c985..d808fdc2c 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/NamedQuery.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/NamedQuery.java @@ -34,6 +34,12 @@ import org.springframework.data.repository.query.RepositoryQuery; */ final class NamedQuery extends AbstractStringBasedJpaQuery { + private static final String CANNOT_EXTRACT_QUERY = + "Your persistence provider does not support extracting the JPQL query from a " + + "named query thus you can't use Pageable inside your query method. Make sure you " + + "have a JpaDialect configured at your EntityManagerFactoryBean as this affects " + + "discovering the concrete persistence provider."; + private static final Logger LOG = LoggerFactory.getLogger(NamedQuery.class); private final String queryName; @@ -49,6 +55,31 @@ final class NamedQuery extends AbstractStringBasedJpaQuery { this.queryName = method.getNamedQueryName(); this.extractor = method.getQueryExtractor(); + + Parameters parameters = method.getParameters(); + + if (parameters.hasSortParameter()) { + throw new IllegalStateException(String.format( + "Finder method %s is backed " + "by a NamedQuery and must " + + "not contain a sort parameter as we " + + "cannot modify the query! Use @Query instead!", + method)); + } + + if (parameters.hasPageableParameter()) { + LOG.info("Finder method {} is backed by a NamedQuery" + + " but contains a Pageble parameter! Sorting deliviered " + + "via this Pageable will not be applied!", method); + } + + boolean weNeedToCreateCountQuery = + method.getParameters().hasPageableParameter(); + boolean cantExtractQuery = !this.extractor.canExtractQuery(); + + if (weNeedToCreateCountQuery && cantExtractQuery) { + throw QueryCreationException.create(method, CANNOT_EXTRACT_QUERY); + } + Query query = em.createNamedQuery(queryName); // Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=322579 @@ -73,40 +104,7 @@ final class NamedQuery extends AbstractStringBasedJpaQuery { LOG.debug("Looking up named query {}", queryName); try { - - RepositoryQuery query = new NamedQuery(method, em); - Parameters parameters = method.getParameters(); - - if (parameters.hasSortParameter()) { - throw new IllegalStateException( - String.format( - "Finder method %s is backed " - + "by a NamedQuery and must " - + "not contain a sort parameter as we " - + "cannot modify the query! Use @Query instead!", - method)); - } - - boolean isPaging = parameters.hasPageableParameter(); - boolean cannotExtractQuery = - !method.getQueryExtractor().canExtractQuery(); - - if (isPaging && cannotExtractQuery) { - throw QueryCreationException - .create(method, - "Cannot use Pageable parameter in query methods with your persistence provider!"); - } - - if (parameters.hasPageableParameter()) { - LOG.info( - "Finder method {} is backed by a NamedQuery" - + " but contains a Pageble parameter! Sorting deliviered " - + "via this Pageable will not be applied!", - method); - - } - - return query; + return new NamedQuery(method, em); } catch (IllegalArgumentException e) { return null; } diff --git a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryMethodUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryMethodUnitTests.java index 79473fd05..b977a15bc 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryMethodUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/JpaQueryMethodUnitTests.java @@ -17,7 +17,6 @@ package org.springframework.data.jpa.repository.query; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; -import static org.mockito.Mockito.*; import java.lang.reflect.Method; import java.util.List; @@ -168,20 +167,6 @@ public class JpaQueryMethodUnitTests { } - @Test(expected = IllegalArgumentException.class) - public void rejectsPageablesOnPersistenceProvidersNotExtractingQueries() - throws Exception { - - Method method = - UserRepository.class.getMethod("findByLastname", - Pageable.class, String.class); - - when(extractor.canExtractQuery()).thenReturn(false); - - new JpaQueryMethod(method, metadata, extractor); - } - - @Test public void recognizesModifyingMethod() { diff --git a/src/test/java/org/springframework/data/jpa/repository/query/NamedQueryUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/NamedQueryUnitTests.java new file mode 100644 index 000000000..7e97c418c --- /dev/null +++ b/src/test/java/org/springframework/data/jpa/repository/query/NamedQueryUnitTests.java @@ -0,0 +1,76 @@ +/* + * 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.*; + +import java.lang.reflect.Method; + +import javax.persistence.EntityManager; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.repository.query.QueryCreationException; +import org.springframework.data.repository.support.RepositoryMetadata; + + +/** + * Unit tests for {@link NamedQuery}. + * + * @author Oliver Gierke + */ +@RunWith(MockitoJUnitRunner.class) +public class NamedQueryUnitTests { + + @Mock + RepositoryMetadata metadata; + @Mock + QueryExtractor extractor; + @Mock + EntityManager em; + + Method method; + + + @Before + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void setUp() throws SecurityException, NoSuchMethodException { + + method = SampleRepository.class.getMethod("foo", Pageable.class); + when(metadata.getDomainClass()).thenReturn((Class) String.class); + } + + + @Test(expected = QueryCreationException.class) + public void rejectsPersistenceProviderIfIncapableOfExtractingQueriesAndPagebleBeingUsed() { + + when(extractor.canExtractQuery()).thenReturn(false); + + JpaQueryMethod queryMethod = + new JpaQueryMethod(method, metadata, extractor); + NamedQuery.lookupFrom(queryMethod, em); + } + + interface SampleRepository { + + Page foo(Pageable pageable); + } +}