DATAJPA-345 - Allow @Lock and @QueryHints to be used as meta-annotations.

@Lock and @QueryHints can now be used as meta annotations to create custom annotations to e.g. reuse a dedicated set of query hints.
This commit is contained in:
Oliver Gierke
2013-05-16 13:24:21 +02:00
parent a3fd29029d
commit a030433d5b
5 changed files with 44 additions and 12 deletions

View File

@@ -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.
@@ -30,7 +30,7 @@ import javax.persistence.LockModeType;
* @author Aleksander Blomskøld
* @author Oliver Gierke
*/
@Target(ElementType.METHOD)
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Lock {
@@ -41,4 +41,4 @@ public @interface Lock {
* @return
*/
LockModeType value();
}
}

View File

@@ -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.
@@ -15,6 +15,7 @@
*/
package org.springframework.data.jpa.repository;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -30,8 +31,9 @@ import javax.persistence.QueryHint;
*
* @author Oliver Gierke
*/
@Target(ElementType.METHOD)
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface QueryHints {
/**

View File

@@ -126,7 +126,7 @@ public class JpaQueryMethod extends QueryMethod {
*/
LockModeType getLockModeType() {
Lock annotation = method.getAnnotation(Lock.class);
Lock annotation = findAnnotation(method, Lock.class);
return (LockModeType) AnnotationUtils.getValue(annotation);
}

View File

@@ -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.
@@ -84,7 +84,7 @@ public enum LockModeRepositoryPostProcessor implements RepositoryProxyPostProces
return invocation.proceed();
}
Lock annotation = method.getAnnotation(Lock.class);
Lock annotation = AnnotationUtils.findAnnotation(method, Lock.class);
LockModeType lockMode = (LockModeType) AnnotationUtils.getValue(annotation);
TransactionSynchronizationManager.bindResource(method, lockMode == null ? NULL : lockMode);

View File

@@ -19,6 +19,8 @@ import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
import java.util.List;
@@ -37,6 +39,7 @@ import org.springframework.data.jpa.domain.sample.User;
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.sample.UserRepository;
import org.springframework.data.repository.core.RepositoryMetadata;
import org.springframework.data.repository.core.support.DefaultRepositoryMetadata;
@@ -60,7 +63,8 @@ public class JpaQueryMethodUnitTests {
RepositoryMetadata metadata;
Method repositoryMethod, invalidReturnType, pageableAndSort, pageableTwice, sortableTwice, modifyingMethod,
nativeQuery, namedQuery, findWithLockMethod, invalidNamedParameter, findsProjections, findsProjection;
nativeQuery, namedQuery, findWithLockMethod, invalidNamedParameter, findsProjections, findsProjection,
withMetaAnnotation;
/**
* @throws Exception
@@ -85,6 +89,8 @@ public class JpaQueryMethodUnitTests {
findsProjections = ValidRepository.class.getMethod("findsProjections");
findsProjection = ValidRepository.class.getMethod("findsProjection");
withMetaAnnotation = ValidRepository.class.getMethod("withMetaAnnotation");
}
@Test
@@ -221,7 +227,7 @@ public class JpaQueryMethodUnitTests {
@Test
public void considersAnnotatedNamedQueryName() {
JpaQueryMethod queryMethod = new JpaQueryMethod(namedQuery, metadata, extractor);
assertThat(queryMethod.getNamedQueryName(), is("Foo.bar"));
assertThat(queryMethod.getNamedQueryName(), is("HateoasAwareSpringDataWebConfiguration.bar"));
}
/**
@@ -256,7 +262,7 @@ public class JpaQueryMethodUnitTests {
public void returnsDefaultCountQueryNameBasedOnConfiguredNamedQueryName() {
JpaQueryMethod method = new JpaQueryMethod(namedQuery, metadata, extractor);
assertThat(method.getNamedCountQueryName(), is("Foo.bar.count"));
assertThat(method.getNamedCountQueryName(), is("HateoasAwareSpringDataWebConfiguration.bar.count"));
}
/**
@@ -293,6 +299,20 @@ public class JpaQueryMethodUnitTests {
assertThat(new JpaQueryMethod(findsProjection, metadata, extractor).isQueryForEntity(), is(false));
}
/**
* @see DATAJPA-345
*/
@Test
public void detectsLockAndQueryHintsOnIfUsedAsMetaAnnotation() {
JpaQueryMethod method = new JpaQueryMethod(withMetaAnnotation, metadata, extractor);
assertThat(method.getLockModeType(), is(LockModeType.OPTIMISTIC_FORCE_INCREMENT));
assertThat(method.getHints(), hasSize(1));
assertThat(method.getHints().get(0).name(), is("foo"));
assertThat(method.getHints().get(0).value(), is("bar"));
}
/**
* Interface to define invalid repository methods for testing.
*
@@ -334,7 +354,7 @@ public class JpaQueryMethodUnitTests {
@Query(value = "query", nativeQuery = true)
List<User> findByLastname(String lastname);
@Query(name = "Foo.bar")
@Query(name = "HateoasAwareSpringDataWebConfiguration.bar")
List<User> findByNamedQuery();
@Lock(LockModeType.PESSIMISTIC_WRITE)
@@ -344,5 +364,15 @@ public class JpaQueryMethodUnitTests {
List<Integer> findsProjections();
Integer findsProjection();
@CustomAnnotation
void withMetaAnnotation();
}
@Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT)
@QueryHints(@QueryHint(name = "foo", value = "bar"))
@Retention(RetentionPolicy.RUNTIME)
static @interface CustomAnnotation {
}
}