From 6a26db86cf72acaffd3b17a2971797bfc6b3d69c Mon Sep 17 00:00:00 2001 From: Thomas Darimont Date: Thu, 7 Nov 2013 14:06:15 +0100 Subject: [PATCH] DATAJPA-424 - Fixed alias detection in manually defined queries using SpEL. ExpressionBasedStringQuery now resolves and evaluates SpEL expressions of the actual query in the constructor and passes the resolved query to the StringQuery constructor. This enables the alias detection mechanism to work properly. Original pull request: #51 --- .../query/ExpressionBasedStringQuery.java | 29 +++++-------------- .../MappedTypeRepositoryIntegrationTests.java | 18 ++++++++++++ .../ExpressionBasedStringQueryUnitTests.java | 14 +++++++++ .../sample/MappedTypeRepository.java | 6 ++++ 4 files changed, 46 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/springframework/data/jpa/repository/query/ExpressionBasedStringQuery.java b/src/main/java/org/springframework/data/jpa/repository/query/ExpressionBasedStringQuery.java index 3acc3329a..230fa87db 100644 --- a/src/main/java/org/springframework/data/jpa/repository/query/ExpressionBasedStringQuery.java +++ b/src/main/java/org/springframework/data/jpa/repository/query/ExpressionBasedStringQuery.java @@ -37,9 +37,6 @@ import org.springframework.util.Assert; class ExpressionBasedStringQuery extends StringQuery { private static final String ENTITY_NAME = "entityName"; - private final JpaEntityMetadata metadata; - - private String parsedQuery; /** * Creates a new {@link ExpressionBasedStringQuery} for the given query and {@link EntityMetadata}. @@ -48,28 +45,18 @@ class ExpressionBasedStringQuery extends StringQuery { * @param metadata must not be {@literal null}. */ public ExpressionBasedStringQuery(String query, JpaEntityMetadata metadata) { - - super(query); - Assert.notNull(metadata, "JpaEntityMetadata must not be null!"); - this.metadata = metadata; + super(renderQueryIfExpressionOrReturnQuery(query, metadata)); } - /* - * (non-Javadoc) - * @see org.springframework.data.jpa.repository.query.StringQuery#getQuery() + /** + * @param query, the query expression potentially containing a SpEL expression. Must not be {@literal null}.} + * @param metadata the {@link JpaEntityMetadata} for the given entity. Must not be {@literal null}. + * @return */ - @Override - public String getQuery() { + private static String renderQueryIfExpressionOrReturnQuery(String query, JpaEntityMetadata metadata) { - if (parsedQuery == null) { - String rawQuery = super.getQuery(); - this.parsedQuery = renderQueryIfExpressionOrReturnQuery(rawQuery); - } - - return this.parsedQuery; - } - - private String renderQueryIfExpressionOrReturnQuery(String query) { + Assert.notNull(query, "query must not be null!"); + Assert.notNull(metadata, "metadata must not be null!"); if (!containsExpression(query)) { return query; diff --git a/src/test/java/org/springframework/data/jpa/repository/MappedTypeRepositoryIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/MappedTypeRepositoryIntegrationTests.java index 463bac057..ec1495a1c 100644 --- a/src/test/java/org/springframework/data/jpa/repository/MappedTypeRepositoryIntegrationTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/MappedTypeRepositoryIntegrationTests.java @@ -25,6 +25,9 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Sort; import org.springframework.data.jpa.domain.sample.ConcreteType1; import org.springframework.data.jpa.domain.sample.ConcreteType2; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @@ -68,4 +71,19 @@ public class MappedTypeRepositoryIntegrationTests { assertThat(concretes1.size(), is(1)); assertThat(concretes2.size(), is(1)); } + + /** + * @see DATAJPA-424 + */ + @Test + public void supportForPaginationCustomQueryMethodsWithEntityExpression() { + + concreteRepository1.save(new ConcreteType1("foo")); + concreteRepository2.save(new ConcreteType2("foo")); + + Page page = concreteRepository2.findByAttribute1Custom("foo", new PageRequest(0, 10, + Sort.Direction.DESC, "attribute1")); + + assertThat(page.getNumberOfElements(), is(1)); + } } diff --git a/src/test/java/org/springframework/data/jpa/repository/query/ExpressionBasedStringQueryUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/ExpressionBasedStringQueryUnitTests.java index 6b5fca1d4..c2f0f235f 100644 --- a/src/test/java/org/springframework/data/jpa/repository/query/ExpressionBasedStringQueryUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/query/ExpressionBasedStringQueryUnitTests.java @@ -48,4 +48,18 @@ public class ExpressionBasedStringQueryUnitTests { StringQuery query = new ExpressionBasedStringQuery(source, metadata); assertThat(query.getQuery(), is("select from User u where u.firstname like :firstname")); } + + /** + * @DATAJPA-424 + */ + @Test + public void renderAliasInExpressionQueryCorrectly() { + + when(metadata.getEntityName()).thenReturn("User"); + + StringQuery query = new ExpressionBasedStringQuery("select u from #{#entityName} u", metadata); + + assertThat(query.getAlias(), is("u")); + assertThat(query.getQuery(), is("select u from User u")); + } } diff --git a/src/test/java/org/springframework/data/jpa/repository/sample/MappedTypeRepository.java b/src/test/java/org/springframework/data/jpa/repository/sample/MappedTypeRepository.java index 5a9ce4a0b..d139b80e8 100644 --- a/src/test/java/org/springframework/data/jpa/repository/sample/MappedTypeRepository.java +++ b/src/test/java/org/springframework/data/jpa/repository/sample/MappedTypeRepository.java @@ -17,9 +17,12 @@ package org.springframework.data.jpa.repository.sample; import java.util.List; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.sample.AbstractMappedType; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; /** * @author Thomas Darimont @@ -28,4 +31,7 @@ public interface MappedTypeRepository extends JpaR @Query("from #{#entityName} t where t.attribute1=?1") List findAllByAttribute1(String attribute1); + + @Query("SELECT o FROM #{#entityName} o where o.attribute1=:attribute1") + Page findByAttribute1Custom(@Param("attribute1") String attribute1, Pageable pageable); }