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
This commit is contained in:
Thomas Darimont
2013-11-07 11:39:10 +01:00
committed by Oliver Gierke
parent 9a279f83cf
commit 23e27f3332
4 changed files with 46 additions and 21 deletions

View File

@@ -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#getQueryString()
/**
* @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 getQueryString() {
private static String renderQueryIfExpressionOrReturnQuery(String query, JpaEntityMetadata<?> metadata) {
if (parsedQuery == null) {
String rawQuery = super.getQueryString();
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;

View File

@@ -23,6 +23,9 @@ import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
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.sample.ConcreteRepository1;
@@ -61,4 +64,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<ConcreteType2> page = concreteRepository2.findByAttribute1Custom("foo", new PageRequest(0, 10,
Sort.Direction.DESC, "attribute1"));
assertThat(page.getNumberOfElements(), is(1));
}
}

View File

@@ -48,4 +48,18 @@ public class ExpressionBasedStringQueryUnitTests {
StringQuery query = new ExpressionBasedStringQuery(source, metadata);
assertThat(query.getQueryString(), 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.getQueryString(), is("select u from User u"));
}
}

View File

@@ -18,9 +18,12 @@ package org.springframework.data.jpa.repository.sample;
import java.util.List;
import org.springframework.context.annotation.Lazy;
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
@@ -30,4 +33,7 @@ public interface MappedTypeRepository<T extends AbstractMappedType> extends JpaR
@Query("from #{#entityName} t where t.attribute1=?1")
List<T> findAllByAttribute1(String attribute1);
@Query("SELECT o FROM #{#entityName} o where o.attribute1=:attribute1")
Page<T> findByAttribute1Custom(@Param("attribute1") String attribute1, Pageable pageable);
}