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
new file mode 100644
index 000000000..3acc3329a
--- /dev/null
+++ b/src/main/java/org/springframework/data/jpa/repository/query/ExpressionBasedStringQuery.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2013 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 org.springframework.data.jpa.repository.support.JpaEntityMetadata;
+import org.springframework.data.repository.core.EntityMetadata;
+import org.springframework.expression.Expression;
+import org.springframework.expression.ParserContext;
+import org.springframework.expression.spel.standard.SpelExpressionParser;
+import org.springframework.expression.spel.support.StandardEvaluationContext;
+import org.springframework.util.Assert;
+
+/**
+ * Extension of {@link StringQuery} that evaluates the given query string as a SpEL template-expression.
+ *
+ * Currently the following template variables are available:
+ *
+ * - {@code #entityName} - the simple class name of the given entity
+ *
+ *
+ * @author Thomas Darimont
+ * @author Oliver Gierke
+ */
+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}.
+ *
+ * @param query must not be {@literal null} or empty.
+ * @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;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.jpa.repository.query.StringQuery#getQuery()
+ */
+ @Override
+ public String getQuery() {
+
+ if (parsedQuery == null) {
+ String rawQuery = super.getQuery();
+ this.parsedQuery = renderQueryIfExpressionOrReturnQuery(rawQuery);
+ }
+
+ return this.parsedQuery;
+ }
+
+ private String renderQueryIfExpressionOrReturnQuery(String query) {
+
+ if (!containsExpression(query)) {
+ return query;
+ }
+
+ StandardEvaluationContext evalContext = new StandardEvaluationContext();
+ evalContext.setVariable(ENTITY_NAME, metadata.getEntityName());
+
+ SpelExpressionParser parser = new SpelExpressionParser();
+ Expression expr = parser.parseExpression(query, ParserContext.TEMPLATE_EXPRESSION);
+
+ Object result = expr.getValue(evalContext, String.class);
+ return result == null ? query : String.valueOf(result);
+ }
+
+ private static boolean containsExpression(String query) {
+ return query.contains("#{#" + ENTITY_NAME + "}");
+ }
+}
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 1eaabf9d3..08e9619ce 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2011 the original author or authors.
+ * Copyright 2008-2013 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.
@@ -30,6 +30,8 @@ import org.springframework.data.jpa.repository.Lock;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.jpa.repository.QueryHints;
+import org.springframework.data.jpa.repository.support.DefaultJpaEntityMetadata;
+import org.springframework.data.jpa.repository.support.JpaEntityMetadata;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.Parameters;
@@ -91,6 +93,16 @@ public class JpaQueryMethod extends QueryMethod {
}
}
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.repository.query.QueryMethod#getEntityInformation()
+ */
+ @Override
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public JpaEntityMetadata> getEntityInformation() {
+ return new DefaultJpaEntityMetadata(getDomainClass());
+ }
+
/**
* Returns whether the finder is a modifying one.
*
diff --git a/src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java b/src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java
index 6b57a3159..7093eaea9 100644
--- a/src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java
+++ b/src/main/java/org/springframework/data/jpa/repository/query/SimpleJpaQuery.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2008-2012 the original author or authors.
+ * Copyright 2008-2013 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.
@@ -32,6 +32,7 @@ import org.springframework.data.repository.query.RepositoryQuery;
* {@link Query} from it.
*
* @author Oliver Gierke
+ * @author Thomas Darimont
*/
final class SimpleJpaQuery extends AbstractJpaQuery {
@@ -50,7 +51,7 @@ final class SimpleJpaQuery extends AbstractJpaQuery {
super(method, em);
this.method = method;
- this.query = new StringQuery(queryString);
+ this.query = new ExpressionBasedStringQuery(queryString, method.getEntityInformation());
Parameters parameters = method.getParameters();
boolean hasPagingOrSortingParameter = parameters.hasPageableParameter() || parameters.hasSortParameter();
diff --git a/src/main/java/org/springframework/data/jpa/repository/support/DefaultJpaEntityMetadata.java b/src/main/java/org/springframework/data/jpa/repository/support/DefaultJpaEntityMetadata.java
new file mode 100644
index 000000000..8e457cd7c
--- /dev/null
+++ b/src/main/java/org/springframework/data/jpa/repository/support/DefaultJpaEntityMetadata.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 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.support;
+
+import javax.persistence.Entity;
+
+import org.springframework.util.Assert;
+import org.springframework.util.StringUtils;
+
+/**
+ * Default implementation for {@link JpaEntityMetadata}.
+ *
+ * @author Oliver Gierke
+ */
+public class DefaultJpaEntityMetadata implements JpaEntityMetadata {
+
+ private final Class domainType;
+
+ /**
+ * Creates a new {@link DefaultJpaEntityMetadata} for the given domain type.
+ *
+ * @param domainType must not be {@literal null}.
+ */
+ public DefaultJpaEntityMetadata(Class domainType) {
+
+ Assert.notNull(domainType, "Domain type must not be null!");
+ this.domainType = domainType;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.repository.core.EntityMetadata#getJavaType()
+ */
+ @Override
+ public Class getJavaType() {
+ return domainType;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.jpa.repository.support.JpaEntityMetadata#getEntityName()
+ */
+ public String getEntityName() {
+
+ Entity entity = domainType.getAnnotation(Entity.class);
+ boolean hasName = null != entity && StringUtils.hasText(entity.name());
+
+ return hasName ? entity.name() : domainType.getSimpleName();
+ }
+}
diff --git a/src/main/java/org/springframework/data/jpa/repository/support/JpaEntityInformation.java b/src/main/java/org/springframework/data/jpa/repository/support/JpaEntityInformation.java
index be13dc1fa..b221f8875 100644
--- a/src/main/java/org/springframework/data/jpa/repository/support/JpaEntityInformation.java
+++ b/src/main/java/org/springframework/data/jpa/repository/support/JpaEntityInformation.java
@@ -27,7 +27,8 @@ import org.springframework.data.repository.core.EntityInformation;
* @author Oliver Gierke
* @author Thomas Darimont
*/
-public interface JpaEntityInformation extends EntityInformation {
+public interface JpaEntityInformation extends EntityInformation,
+ JpaEntityMetadata {
/**
* Returns the id attribute of the entity.
@@ -59,11 +60,4 @@ public interface JpaEntityInformation extends Entity
* @return
*/
Object getCompositeIdAttributeValue(Serializable id, String idAttribute);
-
- /**
- * Returns the JPA entity name.
- *
- * @return
- */
- String getEntityName();
}
diff --git a/src/main/java/org/springframework/data/jpa/repository/support/JpaEntityInformationSupport.java b/src/main/java/org/springframework/data/jpa/repository/support/JpaEntityInformationSupport.java
index 4eb9542a1..b62db08f8 100644
--- a/src/main/java/org/springframework/data/jpa/repository/support/JpaEntityInformationSupport.java
+++ b/src/main/java/org/springframework/data/jpa/repository/support/JpaEntityInformationSupport.java
@@ -17,14 +17,12 @@ package org.springframework.data.jpa.repository.support;
import java.io.Serializable;
-import javax.persistence.Entity;
import javax.persistence.EntityManager;
import javax.persistence.metamodel.Metamodel;
import org.springframework.data.domain.Persistable;
import org.springframework.data.repository.core.support.AbstractEntityInformation;
import org.springframework.util.Assert;
-import org.springframework.util.StringUtils;
/**
* Base class for {@link JpaEntityInformation} implementations to share common method implementations.
@@ -34,14 +32,16 @@ import org.springframework.util.StringUtils;
public abstract class JpaEntityInformationSupport extends AbstractEntityInformation
implements JpaEntityInformation {
+ private JpaEntityMetadata metadata;
+
/**
* Creates a new {@link JpaEntityInformationSupport} with the given domain class.
*
* @param domainClass must not be {@literal null}.
*/
public JpaEntityInformationSupport(Class domainClass) {
-
super(domainClass);
+ this.metadata = new DefaultJpaEntityMetadata(domainClass);
}
/**
@@ -68,17 +68,9 @@ public abstract class JpaEntityInformationSupport ex
/*
* (non-Javadoc)
- *
- * @see
- * org.springframework.data.jpa.repository.support.JpaEntityInformation#
- * getEntityName()
+ * @see org.springframework.data.jpa.repository.support.JpaEntityMetadata#getEntityName()
*/
public String getEntityName() {
-
- Class> domainClass = getJavaType();
- Entity entity = domainClass.getAnnotation(Entity.class);
- boolean hasName = null != entity && StringUtils.hasText(entity.name());
-
- return hasName ? entity.name() : domainClass.getSimpleName();
+ return metadata.getEntityName();
}
}
diff --git a/src/main/java/org/springframework/data/jpa/repository/support/JpaEntityMetadata.java b/src/main/java/org/springframework/data/jpa/repository/support/JpaEntityMetadata.java
new file mode 100644
index 000000000..c54f27c85
--- /dev/null
+++ b/src/main/java/org/springframework/data/jpa/repository/support/JpaEntityMetadata.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013 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.support;
+
+import org.springframework.data.repository.core.EntityMetadata;
+
+/**
+ * JPA specific extension of {@link EntityMetadata}.
+ *
+ * @author Oliver Gierke
+ */
+public interface JpaEntityMetadata extends EntityMetadata {
+
+ /**
+ * Returns the name of the entity.
+ *
+ * @return
+ */
+ String getEntityName();
+}
diff --git a/src/main/java/org/springframework/data/jpa/repository/support/JpaPersistableEntityInformation.java b/src/main/java/org/springframework/data/jpa/repository/support/JpaPersistableEntityInformation.java
index 4269ccbb0..c7b1371c1 100644
--- a/src/main/java/org/springframework/data/jpa/repository/support/JpaPersistableEntityInformation.java
+++ b/src/main/java/org/springframework/data/jpa/repository/support/JpaPersistableEntityInformation.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 the original author or authors.
+ * Copyright 2011-2013 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.
@@ -32,37 +32,28 @@ public class JpaPersistableEntityInformation, ID exten
/**
* Creates a new {@link JpaPersistableEntityInformation} for the given domain class and {@link Metamodel}.
*
- * @param domainClass
- * @param metamodel
+ * @param domainClass must not be {@literal null}.
+ * @param metamodel must not be {@literal null}.
*/
public JpaPersistableEntityInformation(Class domainClass, Metamodel metamodel) {
-
super(domainClass, metamodel);
}
/*
* (non-Javadoc)
- *
- * @see
- * org.springframework.data.repository.support.AbstractEntityInformation
- * #isNew(java.lang.Object)
+ * @see org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation#isNew(java.lang.Object)
*/
@Override
public boolean isNew(T entity) {
-
return entity.isNew();
}
/*
* (non-Javadoc)
- *
- * @see
- * org.springframework.data.jpa.repository.support.JpaMetamodelEntityMetadata
- * #getId(java.lang.Object)
+ * @see org.springframework.data.jpa.repository.support.JpaMetamodelEntityInformation#getId(java.lang.Object)
*/
@Override
public ID getId(T entity) {
-
return entity.getId();
}
}
diff --git a/src/test/java/org/springframework/data/jpa/domain/sample/AbstractMappedType.java b/src/test/java/org/springframework/data/jpa/domain/sample/AbstractMappedType.java
new file mode 100644
index 000000000..07e407922
--- /dev/null
+++ b/src/test/java/org/springframework/data/jpa/domain/sample/AbstractMappedType.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2013 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.domain.sample;
+
+import javax.persistence.GeneratedValue;
+import javax.persistence.Id;
+import javax.persistence.MappedSuperclass;
+
+/**
+ * @author Thomas Darimont
+ */
+@MappedSuperclass
+public abstract class AbstractMappedType {
+
+ public AbstractMappedType() {}
+
+ public AbstractMappedType(String attribute1) {
+ this.attribute1 = attribute1;
+ }
+
+ @Id @GeneratedValue Long id;
+ String attribute1;
+}
diff --git a/src/test/java/org/springframework/data/jpa/domain/sample/ConcreteType1.java b/src/test/java/org/springframework/data/jpa/domain/sample/ConcreteType1.java
new file mode 100644
index 000000000..6ee66ffb8
--- /dev/null
+++ b/src/test/java/org/springframework/data/jpa/domain/sample/ConcreteType1.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 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.domain.sample;
+
+import javax.persistence.Entity;
+
+/**
+ * @author Thomas Darimont
+ */
+@Entity
+public class ConcreteType1 extends AbstractMappedType {
+
+ public ConcreteType1() {}
+
+ public ConcreteType1(String attribute1) {
+ super(attribute1);
+ }
+}
diff --git a/src/test/java/org/springframework/data/jpa/domain/sample/ConcreteType2.java b/src/test/java/org/springframework/data/jpa/domain/sample/ConcreteType2.java
new file mode 100644
index 000000000..abfd0b69d
--- /dev/null
+++ b/src/test/java/org/springframework/data/jpa/domain/sample/ConcreteType2.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 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.domain.sample;
+
+import javax.persistence.Entity;
+
+/**
+ * @author Thomas Darimont
+ */
+@Entity
+public class ConcreteType2 extends AbstractMappedType {
+
+ public ConcreteType2() {}
+
+ public ConcreteType2(String attribute1) {
+ super(attribute1);
+ }
+}
diff --git a/src/test/java/org/springframework/data/jpa/repository/MappedTypeRepositoryIntegrationTests.java b/src/test/java/org/springframework/data/jpa/repository/MappedTypeRepositoryIntegrationTests.java
new file mode 100644
index 000000000..463bac057
--- /dev/null
+++ b/src/test/java/org/springframework/data/jpa/repository/MappedTypeRepositoryIntegrationTests.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2013 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;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.util.List;
+
+import org.junit.Test;
+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.jpa.domain.sample.ConcreteType1;
+import org.springframework.data.jpa.domain.sample.ConcreteType2;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.data.jpa.repository.sample.ConcreteRepository1;
+import org.springframework.data.jpa.repository.sample.ConcreteRepository2;
+import org.springframework.data.jpa.repository.sample.MappedTypeRepository;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * Integration tests for {@link MappedTypeRepository}.
+ *
+ * @author Thomas Darimont
+ */
+@Transactional
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration
+public class MappedTypeRepositoryIntegrationTests {
+
+ @Configuration
+ @ImportResource("classpath:infrastructure.xml")
+ @EnableJpaRepositories
+ static class Config {}
+
+ @Autowired ConcreteRepository1 concreteRepository1;
+ @Autowired ConcreteRepository2 concreteRepository2;
+
+ /**
+ * @see DATAJPA-170
+ */
+ @Test
+ public void supportForExpressionBasedQueryMethods() {
+
+ concreteRepository1.save(new ConcreteType1("foo"));
+ concreteRepository2.save(new ConcreteType2("foo"));
+
+ List concretes1 = concreteRepository1.findAllByAttribute1("foo");
+ List concretes2 = concreteRepository2.findAllByAttribute1("foo");
+
+ assertThat(concretes1.size(), is(1));
+ assertThat(concretes2.size(), 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
new file mode 100644
index 000000000..6b5fca1d4
--- /dev/null
+++ b/src/test/java/org/springframework/data/jpa/repository/query/ExpressionBasedStringQueryUnitTests.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2013 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.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.springframework.data.jpa.repository.support.JpaEntityMetadata;
+
+/**
+ * Unit tests for {@link ExpressionBasedStringQuery}.
+ *
+ * @author Thomas Darimont
+ * @author Oliver Gierke
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class ExpressionBasedStringQueryUnitTests {
+
+ @Mock JpaEntityMetadata> metadata;
+
+ /**
+ * @see DATAJPA-170
+ */
+ @Test
+ public void shouldReturnQueryWithDomainTypeExpressionReplacedWithSimpleDomainTypeName() {
+
+ when(metadata.getEntityName()).thenReturn("User");
+
+ String source = "select from #{#entityName} u where u.firstname like :firstname";
+ StringQuery query = new ExpressionBasedStringQuery(source, metadata);
+ assertThat(query.getQuery(), is("select from User u where u.firstname like :firstname"));
+ }
+}
diff --git a/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java
index e4aaed99e..4ecca6180 100644
--- a/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java
+++ b/src/test/java/org/springframework/data/jpa/repository/query/SimpleJpaQueryUnitTests.java
@@ -42,6 +42,8 @@ import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.sample.User;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.jpa.repository.sample.UserRepository;
+import org.springframework.data.jpa.repository.support.DefaultJpaEntityMetadata;
+import org.springframework.data.jpa.repository.support.JpaEntityMetadata;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.query.Parameters;
@@ -67,24 +69,29 @@ public class SimpleJpaQueryUnitTests {
public @Rule ExpectedException exception = ExpectedException.none();
@Before
+ @SuppressWarnings({ "rawtypes", "unchecked" })
public void setUp() throws SecurityException, NoSuchMethodException {
when(em.createQuery(anyString())).thenReturn(query);
when(em.createQuery(anyString(), eq(Long.class))).thenReturn(query);
when(em.getEntityManagerFactory()).thenReturn(emf);
when(emf.createEntityManager()).thenReturn(em);
+ when(metadata.getDomainType()).thenReturn((Class) User.class);
+ when(metadata.getReturnedDomainClass(Mockito.any(Method.class))).thenReturn((Class) User.class);
Method setUp = UserRepository.class.getMethod("findByLastname", String.class);
method = new JpaQueryMethod(setUp, metadata, extractor);
}
@Test
+ @SuppressWarnings({ "rawtypes", "unchecked" })
public void prefersDeclaredCountQueryOverCreatingOne() throws Exception {
method = mock(JpaQueryMethod.class);
when(method.getCountQuery()).thenReturn("foo");
when(method.getParameters()).thenReturn(
new Parameters(SimpleJpaQueryUnitTests.class.getMethod("prefersDeclaredCountQueryOverCreatingOne")));
+ when(method.getEntityInformation()).thenReturn((JpaEntityMetadata) new DefaultJpaEntityMetadata(User.class));
when(em.createQuery("foo", Long.class)).thenReturn(query);
SimpleJpaQuery jpaQuery = new SimpleJpaQuery(method, em, "select u from User u");
diff --git a/src/test/java/org/springframework/data/jpa/repository/sample/ConcreteRepository1.java b/src/test/java/org/springframework/data/jpa/repository/sample/ConcreteRepository1.java
new file mode 100644
index 000000000..fd27000bc
--- /dev/null
+++ b/src/test/java/org/springframework/data/jpa/repository/sample/ConcreteRepository1.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 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.sample;
+
+import org.springframework.data.jpa.domain.sample.ConcreteType1;
+
+/**
+ * @author Thomas Darimont
+ */
+public interface ConcreteRepository1 extends MappedTypeRepository {
+
+}
diff --git a/src/test/java/org/springframework/data/jpa/repository/sample/ConcreteRepository2.java b/src/test/java/org/springframework/data/jpa/repository/sample/ConcreteRepository2.java
new file mode 100644
index 000000000..41524d83b
--- /dev/null
+++ b/src/test/java/org/springframework/data/jpa/repository/sample/ConcreteRepository2.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2013 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.sample;
+
+import org.springframework.data.jpa.domain.sample.ConcreteType2;
+
+/**
+ * @author Thomas Darimont
+ */
+public interface ConcreteRepository2 extends MappedTypeRepository {
+
+}
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
new file mode 100644
index 000000000..5a9ce4a0b
--- /dev/null
+++ b/src/test/java/org/springframework/data/jpa/repository/sample/MappedTypeRepository.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2013 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.sample;
+
+import java.util.List;
+
+import org.springframework.data.jpa.domain.sample.AbstractMappedType;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+
+/**
+ * @author Thomas Darimont
+ */
+public interface MappedTypeRepository extends JpaRepository {
+
+ @Query("from #{#entityName} t where t.attribute1=?1")
+ List findAllByAttribute1(String attribute1);
+}
diff --git a/src/test/java/org/springframework/data/jpa/repository/support/DefaultJpaEntityMetadataUnitTest.java b/src/test/java/org/springframework/data/jpa/repository/support/DefaultJpaEntityMetadataUnitTest.java
new file mode 100644
index 000000000..b20022182
--- /dev/null
+++ b/src/test/java/org/springframework/data/jpa/repository/support/DefaultJpaEntityMetadataUnitTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2013 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.support;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.*;
+
+import javax.persistence.Entity;
+
+import org.junit.Test;
+
+/**
+ * Unit tests for {@link DefaultJpaEntityMetadata}.
+ *
+ * @author Oliver Gierke
+ */
+public class DefaultJpaEntityMetadataUnitTest {
+
+ @Test(expected = IllegalArgumentException.class)
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public void rejectsNullDomainType() {
+ new DefaultJpaEntityMetadata(null);
+ }
+
+ @Test
+ public void returnsConfiguredType() {
+
+ DefaultJpaEntityMetadata metadata = new DefaultJpaEntityMetadata(Foo.class);
+ assertThat(metadata.getJavaType(), is(equalTo(Foo.class)));
+ }
+
+ @Test
+ public void returnsSimpleClassNameAsEntityNameByDefault() {
+
+ DefaultJpaEntityMetadata metadata = new DefaultJpaEntityMetadata(Foo.class);
+ assertThat(metadata.getEntityName(), is(Foo.class.getSimpleName()));
+ }
+
+ @Test
+ public void returnsCustomizedEntityNameIfConfigured() {
+
+ DefaultJpaEntityMetadata metadata = new DefaultJpaEntityMetadata(Bar.class);
+ assertThat(metadata.getEntityName(), is("Entity"));
+ }
+
+ static class Foo {}
+
+ @Entity(name = "Entity")
+ static class Bar {}
+}
diff --git a/src/test/resources/META-INF/persistence.xml b/src/test/resources/META-INF/persistence.xml
index cfdbee980..3678b4002 100644
--- a/src/test/resources/META-INF/persistence.xml
+++ b/src/test/resources/META-INF/persistence.xml
@@ -15,6 +15,9 @@
org.springframework.data.jpa.domain.sample.SampleEntityPK
org.springframework.data.jpa.domain.sample.SampleWithIdClass
org.springframework.data.jpa.domain.sample.VersionedUser
+ org.springframework.data.jpa.domain.sample.AbstractMappedType
+ org.springframework.data.jpa.domain.sample.ConcreteType1
+ org.springframework.data.jpa.domain.sample.ConcreteType2
true