Use full type information for identifier and domain types exposed byRepositoryMetadata.
See #2518.
This commit is contained in:
committed by
Oliver Drotbohm
parent
21e4fd5ffb
commit
58ed9ce211
@@ -18,16 +18,14 @@ package org.springframework.data.repository.core.support;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.ResolvableType;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.querydsl.User;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
@@ -38,58 +36,59 @@ import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Fabian Buch
|
||||
* @author Alessandro Nistico
|
||||
*/
|
||||
class AbstractRepositoryMetadataUnitTests {
|
||||
|
||||
@Test // DATACMNS-98
|
||||
void discoversSimpleReturnTypeCorrectly() throws Exception {
|
||||
|
||||
RepositoryMetadata metadata = new DummyRepositoryMetadata(UserRepository.class);
|
||||
var method = UserRepository.class.getMethod("findSingle");
|
||||
RepositoryMetadata metadata = new DefaultRepositoryMetadata(UserRepository.class);
|
||||
Method method = UserRepository.class.getMethod("findSingle");
|
||||
assertThat(metadata.getReturnedDomainClass(method)).isEqualTo(User.class);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-98
|
||||
void resolvesTypeParameterReturnType() throws Exception {
|
||||
RepositoryMetadata metadata = new DummyRepositoryMetadata(ConcreteRepository.class);
|
||||
var method = ConcreteRepository.class.getMethod("intermediateMethod");
|
||||
RepositoryMetadata metadata = new DefaultRepositoryMetadata(ConcreteRepository.class);
|
||||
Method method = ConcreteRepository.class.getMethod("intermediateMethod");
|
||||
assertThat(metadata.getReturnedDomainClass(method)).isEqualTo(User.class);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-98
|
||||
void determinesReturnTypeFromPageable() throws Exception {
|
||||
|
||||
RepositoryMetadata metadata = new DummyRepositoryMetadata(ExtendingRepository.class);
|
||||
var method = ExtendingRepository.class.getMethod("findByFirstname", Pageable.class, String.class);
|
||||
RepositoryMetadata metadata = new DefaultRepositoryMetadata(ExtendingRepository.class);
|
||||
Method method = ExtendingRepository.class.getMethod("findByFirstname", Pageable.class, String.class);
|
||||
assertThat(metadata.getReturnedDomainClass(method)).isEqualTo(User.class);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-453
|
||||
void nonPageableRepository() {
|
||||
|
||||
RepositoryMetadata metadata = new DummyRepositoryMetadata(UserRepository.class);
|
||||
RepositoryMetadata metadata = new DefaultRepositoryMetadata(UserRepository.class);
|
||||
assertThat(metadata.isPagingRepository()).isFalse();
|
||||
}
|
||||
|
||||
@Test // DATACMNS-453
|
||||
void pageableRepository() {
|
||||
|
||||
RepositoryMetadata metadata = new DummyRepositoryMetadata(PagedRepository.class);
|
||||
RepositoryMetadata metadata = new DefaultRepositoryMetadata(PagedRepository.class);
|
||||
assertThat(metadata.isPagingRepository()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATACMNS-98
|
||||
void determinesReturnTypeFromGenericType() throws Exception {
|
||||
RepositoryMetadata metadata = new DummyRepositoryMetadata(ExtendingRepository.class);
|
||||
var method = ExtendingRepository.class.getMethod("someMethod");
|
||||
RepositoryMetadata metadata = new DefaultRepositoryMetadata(ExtendingRepository.class);
|
||||
Method method = ExtendingRepository.class.getMethod("someMethod");
|
||||
assertThat(metadata.getReturnedDomainClass(method)).isEqualTo(GenericType.class);
|
||||
}
|
||||
|
||||
@Test // DATACMNS-98
|
||||
void handlesGenericTypeInReturnedCollectionCorrectly() throws SecurityException, NoSuchMethodException {
|
||||
|
||||
RepositoryMetadata metadata = new DummyRepositoryMetadata(ExtendingRepository.class);
|
||||
var method = ExtendingRepository.class.getMethod("anotherMethod");
|
||||
RepositoryMetadata metadata = new DefaultRepositoryMetadata(ExtendingRepository.class);
|
||||
Method method = ExtendingRepository.class.getMethod("anotherMethod");
|
||||
assertThat(metadata.getReturnedDomainClass(method)).isEqualTo(Map.class);
|
||||
}
|
||||
|
||||
@@ -144,23 +143,6 @@ class AbstractRepositoryMetadataUnitTests {
|
||||
|
||||
}
|
||||
|
||||
class DummyRepositoryMetadata extends AbstractRepositoryMetadata {
|
||||
|
||||
DummyRepositoryMetadata(Class<?> repositoryInterface) {
|
||||
super(repositoryInterface);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Class<? extends Serializable> getIdType() {
|
||||
return (Class<? extends Serializable>) ResolvableType//
|
||||
.forClass(Repository.class, getRepositoryInterface()).getGeneric(1).resolve();
|
||||
}
|
||||
|
||||
public Class<?> getDomainType() {
|
||||
return ResolvableType.forClass(Repository.class, getRepositoryInterface()).getGeneric(0).resolve();
|
||||
}
|
||||
}
|
||||
|
||||
// DATACMNS-1299
|
||||
|
||||
class Element {}
|
||||
@@ -171,7 +153,6 @@ class AbstractRepositoryMetadataUnitTests {
|
||||
Container someMethod();
|
||||
}
|
||||
|
||||
interface CompletePageableAndSortingRepository extends PagingAndSortingRepository<Container, Long> {
|
||||
}
|
||||
interface CompletePageableAndSortingRepository extends PagingAndSortingRepository<Container, Long> {}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,12 +29,15 @@ import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.Repository;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.util.ClassUtils;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DefaultRepositoryMetadata}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Alessandro Nistico
|
||||
*/
|
||||
class DefaultRepositoryMetadataUnitTests {
|
||||
|
||||
@@ -79,7 +82,9 @@ class DefaultRepositoryMetadataUnitTests {
|
||||
void detectsParameterizedEntitiesCorrectly() {
|
||||
|
||||
RepositoryMetadata metadata = new DefaultRepositoryMetadata(GenericEntityRepository.class);
|
||||
assertThat(metadata.getDomainType()).isEqualTo(GenericEntity.class);
|
||||
TypeInformation<?> domainType = metadata.getDomainTypeInformation();
|
||||
assertThat(domainType.getType()).isEqualTo(GenericEntity.class);
|
||||
assertThat(domainType.getTypeArguments()).containsExactly(ClassTypeInformation.from(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -36,12 +36,12 @@ public final class DummyRepositoryInformation implements RepositoryInformation {
|
||||
this.metadata = metadata;
|
||||
}
|
||||
|
||||
public Class<?> getIdType() {
|
||||
return metadata.getIdType();
|
||||
public TypeInformation<?> getIdTypeInformation() {
|
||||
return metadata.getIdTypeInformation();
|
||||
}
|
||||
|
||||
public Class<?> getDomainType() {
|
||||
return metadata.getDomainType();
|
||||
public TypeInformation<?> getDomainTypeInformation() {
|
||||
return metadata.getDomainTypeInformation();
|
||||
}
|
||||
|
||||
public Class<?> getRepositoryInterface() {
|
||||
|
||||
@@ -37,11 +37,13 @@ import org.springframework.data.repository.CrudRepository;
|
||||
import org.springframework.data.repository.core.RepositoryInformation;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactoryInformation;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
|
||||
/**
|
||||
* Integration test for {@link DomainClassConverter}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Alessandro Nistico
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class DomainClassConverterIntegrationTests {
|
||||
@@ -64,8 +66,9 @@ class DomainClassConverterIntegrationTests {
|
||||
beanFactory.registerBeanDefinition("postProcessor", new RootBeanDefinition(PredictingProcessor.class));
|
||||
beanFactory.registerBeanDefinition("repoFactory", new RootBeanDefinition(RepositoryFactoryBeanSupport.class));
|
||||
|
||||
doReturn(Person.class).when(information).getDomainType();
|
||||
doReturn(Serializable.class).when(information).getIdType();
|
||||
doReturn(ClassTypeInformation.from(Person.class)).when(information).getDomainTypeInformation();
|
||||
doReturn(ClassTypeInformation.from(Serializable.class)).when(information).getIdTypeInformation();
|
||||
doCallRealMethod().when(information).getDomainType();
|
||||
doReturn(PersonRepository.class).when(factory).getObjectType();
|
||||
doReturn(information).when(factory).getRepositoryInformation();
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Alessandro Nistico
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
@@ -85,7 +86,7 @@ class DomainClassConverterUnitTests {
|
||||
|
||||
converter.setApplicationContext(initContextWithRepo());
|
||||
|
||||
when(service.canConvert(String.class, Long.class)).thenReturn(true);
|
||||
when(service.canConvert(STRING_TYPE, LONG_TYPE)).thenReturn(true);
|
||||
|
||||
assertMatches(true);
|
||||
}
|
||||
@@ -116,7 +117,7 @@ class DomainClassConverterUnitTests {
|
||||
var context = initContextWithRepo();
|
||||
converter.setApplicationContext(context);
|
||||
|
||||
doReturn(1L).when(service).convert(any(), eq(Long.class));
|
||||
doReturn(1L).when(service).convert(any(), eq(STRING_TYPE), eq(LONG_TYPE));
|
||||
|
||||
converter.convert("1", STRING_TYPE, USER_TYPE);
|
||||
|
||||
@@ -133,7 +134,7 @@ class DomainClassConverterUnitTests {
|
||||
var context = new GenericApplicationContext(parent);
|
||||
context.refresh();
|
||||
|
||||
when(service.canConvert(String.class, Long.class)).thenReturn(true);
|
||||
when(service.canConvert(STRING_TYPE, LONG_TYPE)).thenReturn(true);
|
||||
|
||||
converter.setApplicationContext(context);
|
||||
assertThat(converter.matches(STRING_TYPE, USER_TYPE)).isTrue();
|
||||
@@ -169,7 +170,7 @@ class DomainClassConverterUnitTests {
|
||||
|
||||
converter.setApplicationContext(initContextWithRepo());
|
||||
|
||||
when(service.canConvert(Long.class, String.class)).thenReturn(true);
|
||||
when(service.canConvert(LONG_TYPE, STRING_TYPE)).thenReturn(true);
|
||||
assertThat(converter.matches(USER_TYPE, STRING_TYPE)).isTrue();
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,8 @@ import org.springframework.data.repository.core.support.DummyRepositoryFactoryBe
|
||||
import org.springframework.data.repository.core.support.DummyRepositoryInformation;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactoryInformation;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
@@ -56,6 +58,7 @@ import org.springframework.util.ClassUtils;
|
||||
* @author Oliver Gierke
|
||||
* @author Thomas Darimont
|
||||
* @author Jan Zeppenfeld
|
||||
* @author Alessandro Nistico
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@MockitoSettings(strictness = Strictness.LENIENT)
|
||||
@@ -290,7 +293,7 @@ class RepositoriesUnitTests {
|
||||
|
||||
static class CustomRepositoryMetadata extends DefaultRepositoryMetadata {
|
||||
|
||||
private final Class<?> domainType;
|
||||
private final TypeInformation<?> domainType;
|
||||
|
||||
/**
|
||||
* @param repositoryInterface
|
||||
@@ -302,14 +305,14 @@ class RepositoriesUnitTests {
|
||||
var domainType = super.getDomainType().getName().concat("Entity");
|
||||
|
||||
try {
|
||||
this.domainType = ClassUtils.forName(domainType, CustomRepositoryMetadata.class.getClassLoader());
|
||||
this.domainType = ClassTypeInformation.from(ClassUtils.forName(domainType, CustomRepositoryMetadata.class.getClassLoader()));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getDomainType() {
|
||||
public TypeInformation<?> getDomainTypeInformation() {
|
||||
return this.domainType;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user