From 7b3e61e050a952ff2a55536eca83dfa87b17ba63 Mon Sep 17 00:00:00 2001 From: Oliver Gierke Date: Thu, 23 Jun 2011 19:05:49 +0200 Subject: [PATCH] DATACMNS-49 - Added infrastructure to read queries from a Properties file. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added NamedQueries abstraction to hide a map of names to manually defined queries. Added PropertiesBasedNamedQueries to hold the named queries in a Properties instance. Extended resolveQuery(…) method in QueryLookupStrategy to take a NamedQuery instance to allow query creation callback use the named queries. Added optional 'named-queries-location' attribute to the repositories namespace the bean definition parser loads the properties from to populate a PropertiesBasedNamedQueries instance and pipe it into the repository factory. Store implementations have to default the name to lookup in their RepositoryConfiguraion class (see CommonRepositoryConfigInformation.getNamedQueriesLocation()). --- ...tractRepositoryConfigDefinitionParser.java | 4 +- .../CommonRepositoryConfigInformation.java | 6 ++ .../NamedQueriesBeanDefinitionParser.java | 99 +++++++++++++++++++ ...DelegatingRepositoryConfigInformation.java | 8 ++ .../data/repository/core/NamedQueries.java | 41 ++++++++ .../support/PropertiesBasedNamedQueries.java | 57 +++++++++++ .../support/RepositoryFactoryBeanSupport.java | 22 ++++- .../support/RepositoryFactorySupport.java | 14 ++- .../repository/query/QueryLookupStrategy.java | 4 +- .../data/repository/query/QueryMethod.java | 13 +++ .../config/spring-repository-1.0.xsd | 7 ++ .../RepositoryFactorySupportUnitTests.java | 10 +- 12 files changed, 271 insertions(+), 14 deletions(-) create mode 100644 spring-data-commons-core/src/main/java/org/springframework/data/repository/config/NamedQueriesBeanDefinitionParser.java create mode 100644 spring-data-commons-core/src/main/java/org/springframework/data/repository/core/NamedQueries.java create mode 100644 spring-data-commons-core/src/main/java/org/springframework/data/repository/core/support/PropertiesBasedNamedQueries.java diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/config/AbstractRepositoryConfigDefinitionParser.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/config/AbstractRepositoryConfigDefinitionParser.java index 52211e57e..d79cd1453 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/config/AbstractRepositoryConfigDefinitionParser.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/config/AbstractRepositoryConfigDefinitionParser.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2010 the original author or authors. + * 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. @@ -206,6 +206,8 @@ public abstract class AbstractRepositoryConfigDefinitionParser, private Key queryLookupStrategyKey; private Class repositoryInterface; private Object customImplementation; + private NamedQueries namedQueries; /** @@ -79,6 +81,15 @@ public abstract class RepositoryFactoryBeanSupport, this.customImplementation = customImplementation; } + + /** + * Setter to inject a {@link NamedQueries} instance. + * + * @param namedQueries the namedQueries to set + */ + public void setNamedQueries(NamedQueries namedQueries) { + this.namedQueries = namedQueries; + } /* (non-Javadoc) * @see org.springframework.data.repository.support.EntityMetadataProvider#getEntityMetadata() @@ -135,15 +146,16 @@ public abstract class RepositoryFactoryBeanSupport, /* - * (non-Javadoc) - * - * @see - * org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ + * (non-Javadoc) + * + * @see + * org.springframework.beans.factory.InitializingBean#afterPropertiesSet() + */ public void afterPropertiesSet() { this.factory = createRepositoryFactory(); this.factory.setQueryLookupStrategyKey(queryLookupStrategyKey); + this.factory.setNamedQueries(namedQueries); } diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java index e4644ca6f..b289dc9bb 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/core/support/RepositoryFactorySupport.java @@ -30,6 +30,7 @@ import org.springframework.aop.framework.ProxyFactory; import org.springframework.core.GenericTypeResolver; import org.springframework.data.repository.Repository; import org.springframework.data.repository.core.EntityInformation; +import org.springframework.data.repository.core.NamedQueries; import org.springframework.data.repository.core.RepositoryInformation; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.data.repository.query.QueryLookupStrategy; @@ -56,7 +57,7 @@ public abstract class RepositoryFactorySupport { private QueryLookupStrategy.Key queryLookupStrategyKey; private List> queryPostProcessors = new ArrayList>(); - + private NamedQueries namedQueries = PropertiesBasedNamedQueries.EMPTY; /** * Sets the strategy of how to lookup a query to execute finders. @@ -67,6 +68,15 @@ public abstract class RepositoryFactorySupport { this.queryLookupStrategyKey = key; } + + /** + * Configures a {@link NamedQueries} instance to be handed to the {@link QueryLookupStrategy} for query creation. + * + * @param namedQueries the namedQueries to set + */ + public void setNamedQueries(NamedQueries namedQueries) { + this.namedQueries = namedQueries == null ? PropertiesBasedNamedQueries.EMPTY : namedQueries; + } /** @@ -291,7 +301,7 @@ public abstract class RepositoryFactorySupport { for (Method method : repositoryInformation.getQueryMethods()) { RepositoryQuery query = - lookupStrategy.resolveQuery(method, repositoryInformation); + lookupStrategy.resolveQuery(method, repositoryInformation, namedQueries); invokeListeners(query); queries.put(method, query); } diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryLookupStrategy.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryLookupStrategy.java index 6134afc5c..9b9f7d4aa 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryLookupStrategy.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryLookupStrategy.java @@ -18,6 +18,7 @@ package org.springframework.data.repository.query; import java.lang.reflect.Method; import java.util.Locale; +import org.springframework.data.repository.core.NamedQueries; import org.springframework.data.repository.core.RepositoryMetadata; import org.springframework.util.StringUtils; @@ -56,7 +57,8 @@ public interface QueryLookupStrategy { * * @param method * @param metadata + * @param namedQueries * @return */ - RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata); + RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, NamedQueries namedQueries); } \ No newline at end of file diff --git a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryMethod.java b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryMethod.java index 04eccd857..e2a3db1c4 100644 --- a/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryMethod.java +++ b/spring-data-commons-core/src/main/java/org/springframework/data/repository/query/QueryMethod.java @@ -104,6 +104,19 @@ public class QueryMethod { }; } + + /** + * Returns the name of the named query this method belongs to. + * + * @return + */ + public String getNamedQueryName() { + + Class domainClass = getDomainClass(); + return String.format("%s.%s", domainClass.getSimpleName(), + method.getName()); + } + protected Class getDomainClass() { diff --git a/spring-data-commons-core/src/main/resources/org/springframework/data/repository/config/spring-repository-1.0.xsd b/spring-data-commons-core/src/main/resources/org/springframework/data/repository/config/spring-repository-1.0.xsd index 8221d9f43..a0174cccd 100644 --- a/spring-data-commons-core/src/main/resources/org/springframework/data/repository/config/spring-repository-1.0.xsd +++ b/spring-data-commons-core/src/main/resources/org/springframework/data/repository/config/spring-repository-1.0.xsd @@ -34,6 +34,13 @@ ]]> + + + + + diff --git a/spring-data-commons-core/src/test/java/org/springframework/data/repository/core/support/RepositoryFactorySupportUnitTests.java b/spring-data-commons-core/src/test/java/org/springframework/data/repository/core/support/RepositoryFactorySupportUnitTests.java index ec9272a7c..27c72ea0f 100644 --- a/spring-data-commons-core/src/test/java/org/springframework/data/repository/core/support/RepositoryFactorySupportUnitTests.java +++ b/spring-data-commons-core/src/test/java/org/springframework/data/repository/core/support/RepositoryFactorySupportUnitTests.java @@ -15,7 +15,7 @@ */ package org.springframework.data.repository.core.support; -import static org.mockito.Matchers.any; +import static org.mockito.Matchers.*; import static org.mockito.Mockito.*; import java.io.Serializable; @@ -28,12 +28,11 @@ import org.mockito.runners.MockitoJUnitRunner; import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.Repository; import org.springframework.data.repository.core.EntityInformation; +import org.springframework.data.repository.core.NamedQueries; import org.springframework.data.repository.core.RepositoryMetadata; -import org.springframework.data.repository.core.support.QueryCreationListener; -import org.springframework.data.repository.core.support.RepositoryFactorySupport; import org.springframework.data.repository.query.QueryLookupStrategy; -import org.springframework.data.repository.query.RepositoryQuery; import org.springframework.data.repository.query.QueryLookupStrategy.Key; +import org.springframework.data.repository.query.RepositoryQuery; /** @@ -89,6 +88,7 @@ public class RepositoryFactorySupportUnitTests { verify(backingRepo, times(0)).findOne(1); } + class DummyRepositoryFactory extends RepositoryFactorySupport { /* (non-Javadoc) @@ -123,7 +123,7 @@ public class RepositoryFactorySupportUnitTests { RepositoryQuery queryTwo = mock(RepositoryQuery.class); QueryLookupStrategy strategy = mock(QueryLookupStrategy.class); - when(strategy.resolveQuery(any(Method.class), any(RepositoryMetadata.class))) + when(strategy.resolveQuery(any(Method.class), any(RepositoryMetadata.class), any(NamedQueries.class))) .thenReturn(queryOne, queryTwo); return strategy;