Skip to content

Commit a1509f9

Browse files
christophstroblodrotbohm
authored andcommitted
DATAJPA-871 - Allow usage of composed annotations using @AliasFor.
We allow and support composing annotations for: @entity, @entitygraph, @lock, @Modifying, @query, @QueryHints as well as @procedure. Original pull request: #166.
1 parent 154e337 commit a1509f9

File tree

11 files changed

+344
-40
lines changed

11 files changed

+344
-40
lines changed

src/main/java/org/springframework/data/jpa/repository/EntityGraph.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2015 the original author or authors.
2+
* Copyright 2014-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -30,6 +30,7 @@
3030
*
3131
* Since 1.9 we support the definition of dynamic {@link EntityGraph}s by allowing to customize the fetch-graph via
3232
* via {@link #attributePaths()} ad-hoc fetch-graph configuration.
33+
* @author Christoph Strobl
3334
*
3435
* If {@link #attributePaths()} are specified then we ignore the entity-graph name {@link #value()}
3536
* and treat this {@link EntityGraph} as dynamic.
@@ -38,7 +39,7 @@
3839
* @since 1.6
3940
*/
4041
@Retention(RetentionPolicy.RUNTIME)
41-
@Target(ElementType.METHOD)
42+
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
4243
@Documented
4344
public @interface EntityGraph {
4445

src/main/java/org/springframework/data/jpa/repository/Modifying.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2015 the original author or authors.
2+
* Copyright 2008-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,9 +25,10 @@
2525
* Indicates a method should be regarded as modifying query.
2626
*
2727
* @author Oliver Gierke
28+
* @author Christoph Strobl
2829
*/
2930
@Retention(RetentionPolicy.RUNTIME)
30-
@Target(ElementType.METHOD)
31+
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
3132
@Documented
3233
public @interface Modifying {
3334

src/main/java/org/springframework/data/jpa/repository/Query.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2014 the original author or authors.
2+
* Copyright 2008-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -28,9 +28,10 @@
2828
*
2929
* @author Oliver Gierke
3030
* @author Thomas Darimont
31+
* @author Christoph Strobl
3132
*/
3233
@Retention(RetentionPolicy.RUNTIME)
33-
@Target(ElementType.METHOD)
34+
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
3435
@QueryAnnotation
3536
@Documented
3637
public @interface Query {

src/main/java/org/springframework/data/jpa/repository/query/DefaultJpaEntityMetadata.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2013-2014 the original author or authors.
2+
* Copyright 2013-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -17,13 +17,15 @@
1717

1818
import javax.persistence.Entity;
1919

20+
import org.springframework.core.annotation.AnnotatedElementUtils;
2021
import org.springframework.util.Assert;
2122
import org.springframework.util.StringUtils;
2223

2324
/**
2425
* Default implementation for {@link JpaEntityMetadata}.
2526
*
2627
* @author Oliver Gierke
28+
* @author Christoph Strobl
2729
*/
2830
public class DefaultJpaEntityMetadata<T> implements JpaEntityMetadata<T> {
2931

@@ -55,7 +57,7 @@ public Class<T> getJavaType() {
5557
*/
5658
public String getEntityName() {
5759

58-
Entity entity = domainType.getAnnotation(Entity.class);
60+
Entity entity = AnnotatedElementUtils.findMergedAnnotation(domainType, Entity.class);
5961
boolean hasName = null != entity && StringUtils.hasText(entity.name());
6062

6163
return hasName ? entity.name() : domainType.getSimpleName();

src/main/java/org/springframework/data/jpa/repository/query/JpaQueryMethod.java

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2008-2015 the original author or authors.
2+
* Copyright 2008-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,8 +15,7 @@
1515
*/
1616
package org.springframework.data.jpa.repository.query;
1717

18-
import static org.springframework.core.annotation.AnnotationUtils.*;
19-
18+
import java.lang.annotation.Annotation;
2019
import java.lang.reflect.Method;
2120
import java.util.ArrayList;
2221
import java.util.Arrays;
@@ -28,6 +27,7 @@
2827
import javax.persistence.LockModeType;
2928
import javax.persistence.QueryHint;
3029

30+
import org.springframework.core.annotation.AnnotatedElementUtils;
3131
import org.springframework.core.annotation.AnnotationUtils;
3232
import org.springframework.data.jpa.provider.QueryExtractor;
3333
import org.springframework.data.jpa.repository.EntityGraph;
@@ -48,6 +48,7 @@
4848
*
4949
* @author Oliver Gierke
5050
* @author Thomas Darimont
51+
* @author Christoph Strobl
5152
*/
5253
public class JpaQueryMethod extends QueryMethod {
5354

@@ -135,7 +136,7 @@ public JpaEntityMetadata<?> getEntityInformation() {
135136
@Override
136137
public boolean isModifyingQuery() {
137138

138-
return null != method.getAnnotation(Modifying.class);
139+
return null != AnnotationUtils.findAnnotation(method, Modifying.class);
139140
}
140141

141142
/**
@@ -147,7 +148,7 @@ List<QueryHint> getHints() {
147148

148149
List<QueryHint> result = new ArrayList<QueryHint>();
149150

150-
QueryHints hints = getAnnotation(method, QueryHints.class);
151+
QueryHints hints = AnnotatedElementUtils.findMergedAnnotation(method, QueryHints.class);
151152
if (hints != null) {
152153
result.addAll(Arrays.asList(hints.value()));
153154
}
@@ -162,7 +163,7 @@ List<QueryHint> getHints() {
162163
*/
163164
LockModeType getLockModeType() {
164165

165-
Lock annotation = findAnnotation(method, Lock.class);
166+
Lock annotation = AnnotatedElementUtils.findMergedAnnotation(method, Lock.class);
166167
return (LockModeType) AnnotationUtils.getValue(annotation);
167168
}
168169

@@ -174,7 +175,7 @@ LockModeType getLockModeType() {
174175
*/
175176
JpaEntityGraph getEntityGraph() {
176177

177-
EntityGraph annotation = findAnnotation(method, EntityGraph.class);
178+
EntityGraph annotation = AnnotatedElementUtils.findMergedAnnotation(method, EntityGraph.class);
178179
return annotation == null ? null : new JpaEntityGraph(annotation, getNamedQueryName());
179180
}
180181

@@ -186,7 +187,7 @@ JpaEntityGraph getEntityGraph() {
186187
*/
187188
boolean applyHintsToCountQuery() {
188189

189-
QueryHints hints = getAnnotation(method, QueryHints.class);
190+
QueryHints hints = AnnotatedElementUtils.findMergedAnnotation(method, QueryHints.class);
190191
return hints != null ? hints.forCounting() : false;
191192
}
192193

@@ -284,8 +285,7 @@ String getNamedCountQueryName() {
284285
* @return
285286
*/
286287
boolean getClearAutomatically() {
287-
288-
return (Boolean) AnnotationUtils.getValue(method.getAnnotation(Modifying.class), "clearAutomatically");
288+
return getMergedOrDefaultAnnotationValue("clearAutomatically", Modifying.class, Boolean.class);
289289
}
290290

291291
/**
@@ -298,12 +298,18 @@ boolean getClearAutomatically() {
298298
* @return
299299
*/
300300
private <T> T getAnnotationValue(String attribute, Class<T> type) {
301+
return getMergedOrDefaultAnnotationValue(attribute, Query.class, type);
302+
}
301303

302-
Query annotation = method.getAnnotation(Query.class);
303-
Object value = annotation == null ? AnnotationUtils.getDefaultValue(Query.class, attribute)
304-
: AnnotationUtils.getValue(annotation, attribute);
304+
@SuppressWarnings({ "rawtypes", "unchecked" })
305+
private <T> T getMergedOrDefaultAnnotationValue(String attribute, Class annotationType, Class<T> targetType) {
306+
307+
Annotation annotation = AnnotatedElementUtils.findMergedAnnotation(method, annotationType);
308+
if (annotation == null) {
309+
return targetType.cast(AnnotationUtils.getDefaultValue(annotationType, attribute));
310+
}
305311

306-
return type.cast(value);
312+
return targetType.cast(AnnotationUtils.getValue(annotation, attribute));
307313
}
308314

309315
/*
@@ -339,7 +345,7 @@ public boolean isCollectionQuery() {
339345
* @return
340346
*/
341347
public boolean isProcedureQuery() {
342-
return method.getAnnotation(Procedure.class) != null;
348+
return AnnotationUtils.findAnnotation(method, Procedure.class) != null;
343349
}
344350

345351
/**

src/main/java/org/springframework/data/jpa/repository/query/Procedure.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014 the original author or authors.
2+
* Copyright 2014-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,9 +25,10 @@
2525
*
2626
* @author Thomas Darimont
2727
* @author Oliver Gierke
28+
* @author Christoph Strobl
2829
* @since 1.6
2930
*/
30-
@Target(ElementType.METHOD)
31+
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
3132
@Retention(RetentionPolicy.RUNTIME)
3233
public @interface Procedure {
3334

src/main/java/org/springframework/data/jpa/repository/query/StoredProcedureAttributeSource.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2014-2015 the original author or authors.
2+
* Copyright 2014-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
2424
import javax.persistence.NamedStoredProcedureQuery;
2525
import javax.persistence.StoredProcedureParameter;
2626

27+
import org.springframework.core.annotation.AnnotatedElementUtils;
2728
import org.springframework.util.Assert;
2829
import org.springframework.util.StringUtils;
2930

@@ -32,6 +33,7 @@
3233
*
3334
* @author Thomas Darimont
3435
* @author Oliver Gierke
36+
* @author Christoph Strobl
3537
* @since 1.6
3638
*/
3739
enum StoredProcedureAttributeSource {
@@ -50,7 +52,7 @@ public StoredProcedureAttributes createFrom(Method method, JpaEntityMetadata<?>
5052
Assert.notNull(method, "Method must not be null!");
5153
Assert.notNull(entityMetadata, "EntityMetadata must not be null!");
5254

53-
Procedure procedure = method.getAnnotation(Procedure.class);
55+
Procedure procedure = AnnotatedElementUtils.findMergedAnnotation(method, Procedure.class);
5456
Assert.notNull(procedure, "Method must have an @Procedure annotation!");
5557

5658
NamedStoredProcedureQuery namedStoredProc = tryFindAnnotatedNamedStoredProcedureQuery(method, entityMetadata,
@@ -201,12 +203,14 @@ private List<NamedStoredProcedureQuery> collectNamedStoredProcedureQueriesFrom(C
201203

202204
List<NamedStoredProcedureQuery> queries = new ArrayList<NamedStoredProcedureQuery>();
203205

204-
NamedStoredProcedureQueries namedQueriesAnnotation = entityType.getAnnotation(NamedStoredProcedureQueries.class);
206+
NamedStoredProcedureQueries namedQueriesAnnotation = AnnotatedElementUtils.findMergedAnnotation(entityType,
207+
NamedStoredProcedureQueries.class);
205208
if (namedQueriesAnnotation != null) {
206209
queries.addAll(Arrays.asList(namedQueriesAnnotation.value()));
207210
}
208211

209-
NamedStoredProcedureQuery namedQueryAnnotation = entityType.getAnnotation(NamedStoredProcedureQuery.class);
212+
NamedStoredProcedureQuery namedQueryAnnotation = AnnotatedElementUtils.findMergedAnnotation(entityType,
213+
NamedStoredProcedureQuery.class);
210214
if (namedQueryAnnotation != null) {
211215
queries.add(namedQueryAnnotation);
212216
}

src/main/java/org/springframework/data/jpa/repository/support/CrudMethodMetadataPostProcessor.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2011-2015 the original author or authors.
2+
* Copyright 2011-2016 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -31,6 +31,7 @@
3131
import org.springframework.aop.framework.ProxyFactory;
3232
import org.springframework.aop.interceptor.ExposeInvocationInterceptor;
3333
import org.springframework.beans.factory.BeanClassLoaderAware;
34+
import org.springframework.core.annotation.AnnotatedElementUtils;
3435
import org.springframework.core.annotation.AnnotationUtils;
3536
import org.springframework.data.jpa.repository.EntityGraph;
3637
import org.springframework.data.jpa.repository.Lock;
@@ -48,6 +49,7 @@
4849
*
4950
* @author Oliver Gierke
5051
* @author Thomas Darimont
52+
* @author Christoph Strobl
5153
*/
5254
class CrudMethodMetadataPostProcessor implements RepositoryProxyPostProcessor, BeanClassLoaderAware {
5355

@@ -164,19 +166,19 @@ public DefaultCrudMethodMetadata(Method method) {
164166
}
165167

166168
private static EntityGraph findEntityGraph(Method method) {
167-
return AnnotationUtils.findAnnotation(method, EntityGraph.class);
169+
return AnnotatedElementUtils.findMergedAnnotation(method, EntityGraph.class);
168170
}
169171

170172
private static LockModeType findLockModeType(Method method) {
171173

172-
Lock annotation = AnnotationUtils.findAnnotation(method, Lock.class);
174+
Lock annotation = AnnotatedElementUtils.findMergedAnnotation(method, Lock.class);
173175
return annotation == null ? null : (LockModeType) AnnotationUtils.getValue(annotation);
174176
}
175177

176178
private static Map<String, Object> findQueryHints(Method method) {
177179

178180
Map<String, Object> queryHints = new HashMap<String, Object>();
179-
QueryHints queryHintsAnnotation = AnnotationUtils.findAnnotation(method, QueryHints.class);
181+
QueryHints queryHintsAnnotation = AnnotatedElementUtils.findMergedAnnotation(method, QueryHints.class);
180182

181183
if (queryHintsAnnotation != null) {
182184

0 commit comments

Comments
 (0)