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:
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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()));
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user