Use full type information for identifier and domain types exposed byRepositoryMetadata.

See #2518.
This commit is contained in:
Alex Nistico
2021-12-31 05:43:17 +01:00
committed by Oliver Drotbohm
parent 21e4fd5ffb
commit 58ed9ce211
17 changed files with 161 additions and 92 deletions

View File

@@ -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> {}
}

View File

@@ -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

View File

@@ -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() {

View File

@@ -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();

View File

@@ -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();
}

View File

@@ -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;
}