DATAJPA-173 - Extended support for metadata detection on CRUD methods.

Extended the mechanism previously existing to detect @Lock annotations on redeclared CRUD methods into one being able to transport arbitrary metadata into the execution of CRUD methods.

Renamed LockModeRepositoryPostProcessor to CrudMethodMetadataPostProcessor, refactored the internals and added some metadata caching to avoid repeated reflection lookups to evaluate annotations.
This commit is contained in:
Oliver Gierke
2014-03-12 15:30:46 +01:00
parent 79b5330928
commit 5438c44c8f
10 changed files with 283 additions and 183 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011-2013 the original author or authors.
* Copyright 2011-2014 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.
@@ -19,6 +19,8 @@ import static org.mockito.Matchers.*;
import static org.mockito.Mockito.*;
import java.io.Serializable;
import java.util.Collections;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.LockModeType;
@@ -42,7 +44,7 @@ import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
* @author Oliver Gierke
*/
@RunWith(MockitoJUnitRunner.class)
public class LockIntegrationTests {
public class CrudMethodMetadataIntegrationTests {
@Mock EntityManager em;
@Mock CriteriaBuilder builder;
@@ -69,7 +71,7 @@ public class LockIntegrationTests {
}
/**
* @see DATAJPA-73
* @see DATAJPA-73, DATAJPA-173
*/
@Test
public void usesLockInformationAnnotatedAtRedeclaredMethod() {
@@ -82,16 +84,20 @@ public class LockIntegrationTests {
repository.findAll();
verify(query).setLockMode(LockModeType.READ);
verify(query).setHint("foo", "bar");
}
/**
* @see DATAJPA-359
* @see DATAJPA-359, DATAJPA-173
*/
@Test
public void usesLockInformationAnnotatedAtRedeclaredFindOne() {
public void usesMetadataAnnotatedAtRedeclaredFindOne() {
repository.findOne(1);
verify(em).find(Role.class, 1, LockModeType.READ);
Map<String, Object> expectedLinks = Collections.singletonMap("foo", (Object) "bar");
LockModeType expectedLockModeType = LockModeType.READ;
verify(em).find(Role.class, 1, expectedLockModeType, expectedLinks);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2008-2011 the original author or authors.
* Copyright 2008-2014 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.
@@ -21,9 +21,9 @@ import java.io.Serializable;
import javax.persistence.EntityManager;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.JpaRepositoryFactory;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.data.repository.core.RepositoryMetadata;
/**
@@ -43,14 +43,11 @@ public class CustomGenericJpaRepositoryFactory extends JpaRepositoryFactory {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.jpa.repository.support.GenericJpaRepositoryFactory
* #getTargetRepository(java.lang.Class, javax.persistence.EntityManager)
* @see org.springframework.data.jpa.repository.support.JpaRepositoryFactory#getTargetRepository(org.springframework.data.repository.core.RepositoryMetadata, javax.persistence.EntityManager)
*/
@Override
@SuppressWarnings("unchecked")
protected JpaRepository<?, ?> getTargetRepository(RepositoryMetadata metadata, EntityManager em) {
protected SimpleJpaRepository<?, ?> getTargetRepository(RepositoryMetadata metadata, EntityManager em) {
JpaEntityInformation<Object, Serializable> entityMetadata = mock(JpaEntityInformation.class);
when(entityMetadata.getJavaType()).thenReturn((Class<Object>) metadata.getDomainType());
@@ -59,14 +56,10 @@ public class CustomGenericJpaRepositoryFactory extends JpaRepositoryFactory {
/*
* (non-Javadoc)
*
* @see
* org.springframework.data.repository.support.RepositoryFactorySupport#
* getRepositoryBaseClass()
* @see org.springframework.data.jpa.repository.support.JpaRepositoryFactory#getRepositoryBaseClass(org.springframework.data.repository.core.RepositoryMetadata)
*/
@Override
protected Class<?> getRepositoryBaseClass(RepositoryMetadata metadata) {
return CustomGenericJpaRepository.class;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2008-2011 the original author or authors.
* Copyright 2008-2014 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.
@@ -16,9 +16,11 @@
package org.springframework.data.jpa.repository.sample;
import javax.persistence.LockModeType;
import javax.persistence.QueryHint;
import org.springframework.data.jpa.domain.sample.Role;
import org.springframework.data.jpa.repository.Lock;
import org.springframework.data.jpa.repository.QueryHints;
import org.springframework.data.repository.CrudRepository;
/**
@@ -33,6 +35,7 @@ public interface RoleRepository extends CrudRepository<Role, Integer> {
* @see org.springframework.data.repository.CrudRepository#findAll()
*/
@Lock(LockModeType.READ)
@QueryHints(@QueryHint(name = "foo", value = "bar"))
Iterable<Role> findAll();
/*
@@ -40,5 +43,6 @@ public interface RoleRepository extends CrudRepository<Role, Integer> {
* @see org.springframework.data.repository.CrudRepository#findOne(java.io.Serializable)
*/
@Lock(LockModeType.READ)
@QueryHints(@QueryHint(name = "foo", value = "bar"))
Role findOne(Integer id);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2012 the original author or authors.
* Copyright 2012-2014 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.
@@ -29,19 +29,18 @@ import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.data.jpa.repository.Lock;
import org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor.LockModePopulatingMethodIntercceptor;
import org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor.CrudMethodMetadataPopulatingMethodIntercceptor;
import org.springframework.transaction.support.TransactionSynchronizationManager;
/**
* Unit tests for {@link LockModePopulatingMethodIntercceptor}.
* Unit tests for {@link CrudMethodMetadataPopulatingMethodIntercceptor}.
*
* @author Oliver Gierke
*/
@RunWith(MockitoJUnitRunner.class)
public class LockModePopulatingMethodInterceptorUnitTests {
public class CrudMethodMetadataPopulatingMethodInterceptorUnitTests {
@Mock
MethodInvocation invocation;
@Mock MethodInvocation invocation;
/**
* @see DATAJPA-268
@@ -52,7 +51,7 @@ public class LockModePopulatingMethodInterceptorUnitTests {
Method method = Sample.class.getMethod("someMethod");
when(invocation.getMethod()).thenReturn(method);
LockModePopulatingMethodIntercceptor interceptor = LockModePopulatingMethodIntercceptor.INSTANCE;
CrudMethodMetadataPopulatingMethodIntercceptor interceptor = CrudMethodMetadataPopulatingMethodIntercceptor.INSTANCE;
interceptor.invoke(invocation);
assertThat(TransactionSynchronizationManager.getResource(method), is(nullValue()));

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2011 the original author or authors.
* Copyright 2011-2014 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.
@@ -41,20 +41,14 @@ public class SimpleJpaRepositoryUnitTests {
SimpleJpaRepository<User, Long> repo;
@Mock
EntityManager em;
@Mock
CriteriaBuilder builder;
@Mock
CriteriaQuery<User> criteriaQuery;
@Mock
CriteriaQuery<Long> countCriteriaQuery;
@Mock
TypedQuery<User> query;
@Mock
TypedQuery<Long> countQuery;
@Mock
JpaEntityInformation<User, Long> information;
@Mock EntityManager em;
@Mock CriteriaBuilder builder;
@Mock CriteriaQuery<User> criteriaQuery;
@Mock CriteriaQuery<Long> countCriteriaQuery;
@Mock TypedQuery<User> query;
@Mock TypedQuery<Long> countQuery;
@Mock JpaEntityInformation<User, Long> information;
@Mock CrudMethodMetadata metadata;
@Before
public void setUp() {
@@ -69,6 +63,7 @@ public class SimpleJpaRepositoryUnitTests {
when(em.createQuery(countCriteriaQuery)).thenReturn(countQuery);
repo = new SimpleJpaRepository<User, Long>(information, em);
repo.setRepositoryMethodMetadata(metadata);
}
/**