DATAJPA-1234 - Polishing.

We now make use of the newly introduced BeanLookup in Spring Data Commons to obtain EntityPathResolver instances from the injected BeanFactory.

Polished test cases.

Original pull request: #239.
Related tickets: DATACMNS-1235.
This commit is contained in:
Oliver Gierke
2018-01-10 13:07:59 +01:00
parent 80798f664d
commit a75c44f635
2 changed files with 38 additions and 70 deletions

View File

@@ -15,20 +15,19 @@
*/
package org.springframework.data.jpa.repository.support;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.querydsl.EntityPathResolver;
import org.springframework.data.querydsl.SimpleEntityPathResolver;
import org.springframework.data.repository.Repository;
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
import org.springframework.data.repository.core.support.TransactionalRepositoryFactoryBeanSupport;
import org.springframework.data.util.BeanLookup;
import org.springframework.data.util.Lazy;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
@@ -46,7 +45,7 @@ public class JpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID>
extends TransactionalRepositoryFactoryBeanSupport<T, S, ID> {
private @Nullable EntityManager entityManager;
private EntityPathResolver entityPathResolver = SimpleEntityPathResolver.INSTANCE;
private Lazy<EntityPathResolver> entityPathResolver = Lazy.of(SimpleEntityPathResolver.INSTANCE);
/**
* Creates a new {@link JpaRepositoryFactoryBean} for the given repository interface.
@@ -78,9 +77,7 @@ public class JpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID>
/*
* (non-Javadoc)
*
* @see org.springframework.data.repository.support.
* TransactionalRepositoryFactoryBeanSupport#doCreateRepositoryFactory()
* @see org.springframework.data.repository.core.support.TransactionalRepositoryFactoryBeanSupport#doCreateRepositoryFactory()
*/
@Override
protected RepositoryFactorySupport doCreateRepositoryFactory() {
@@ -95,8 +92,11 @@ public class JpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID>
*/
protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) {
EntityPathResolver resolver = entityPathResolver.get();
JpaRepositoryFactory jpaRepositoryFactory = new JpaRepositoryFactory(entityManager);
jpaRepositoryFactory.setEntityPathResolver(entityPathResolver);
jpaRepositoryFactory.setEntityPathResolver(resolver);
return jpaRepositoryFactory;
}
@@ -113,41 +113,16 @@ public class JpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID>
}
/*
* (non-Javadoc)
* @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory)
*/
* (non-Javadoc)
* @see org.springframework.data.repository.core.support.TransactionalRepositoryFactoryBeanSupport#setBeanFactory(org.springframework.beans.factory.BeanFactory)
*/
public void setBeanFactory(BeanFactory beanFactory) {
Assert.isInstanceOf(ListableBeanFactory.class, beanFactory);
super.setBeanFactory(beanFactory);
entityPathResolver = obtainEntityPathResolver((ListableBeanFactory) beanFactory);
this.entityPathResolver = BeanLookup.lazyIfAvailable(EntityPathResolver.class, beanFactory) //
.or(SimpleEntityPathResolver.INSTANCE);
}
private EntityPathResolver obtainEntityPathResolver(ListableBeanFactory listableBeanFactory) {
Map<String, EntityPathResolver> entityPathResolverMap = listableBeanFactory
.getBeansOfType(EntityPathResolver.class);
switch (entityPathResolverMap.size()) {
case 0:
return SimpleEntityPathResolver.INSTANCE;
case 1:
return entityPathResolverMap.values().iterator().next();
default:
return entityPathResolverMap.computeIfAbsent( //
"entityPathResolver", //
key -> { //
throw new NoUniqueBeanDefinitionException( //
EntityPathResolver.class, //
entityPathResolverMap.size(), //
"No unique EntityPathResolver found, nor one name 'entityPathResolver'" //
);
});
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2017 the original author or authors.
* Copyright 2017-2018 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.
@@ -18,10 +18,11 @@ package org.springframework.data.jpa.repository.support;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.EntityManager;
import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.factory.ListableBeanFactory;
@@ -29,7 +30,15 @@ import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
import org.springframework.data.querydsl.EntityPathResolver;
import org.springframework.data.querydsl.SimpleEntityPathResolver;
import org.springframework.data.repository.Repository;
import org.springframework.data.util.Lazy;
import org.springframework.test.util.ReflectionTestUtils;
/**
* Unit tests for {@link EntityPathResolver} related tests on {@link JpaRepositoryFactoryBean}.
*
* @author Jens Schauder
* @author Oliver Gierke
*/
public class JpaRepositoryFactoryBeanEntityPathResolverUnitTests {
ListableBeanFactory beanFactory = mock(ListableBeanFactory.class);
@@ -41,65 +50,49 @@ public class JpaRepositoryFactoryBeanEntityPathResolverUnitTests {
@Before
public void setup() {
doReturn(beans).when(beanFactory).getBeansOfType(EntityPathResolver.class);
doReturn(beans).when(beanFactory).getBeansOfType(EntityPathResolver.class, false, false);
}
@Test
@Test // DATAJPA-1234
public void withoutConfiguredBeanTheDefaultInstanceIsUsed() throws Exception {
factoryBean.setBeanFactory(beanFactory);
Object entityPathResolver = extractEntityPathResolver(factoryBean);
assertThat(entityPathResolver).isEqualTo(SimpleEntityPathResolver.INSTANCE);
assertThat(extractEntityPathResolver(factoryBean).get()).isEqualTo(SimpleEntityPathResolver.INSTANCE);
}
@Test
@Test // DATAJPA-1234
public void aSingleBeanOfTypeEntityPathResolverIsUsed() throws Exception {
beans.put("irrelevant", pathResolver);
factoryBean.setBeanFactory(beanFactory);
Object entityPathResolver = extractEntityPathResolver(factoryBean);
assertThat(entityPathResolver).isEqualTo(pathResolver);
assertThat(extractEntityPathResolver(factoryBean).get()).isEqualTo(pathResolver);
}
@Test
public void anEntityPathResolverWithProperNameIsUsed() throws Exception {
beans.put("entityPathResolver", pathResolver);
beans.put("irrelevant", new SimpleEntityPathResolver("anotherSuffix"));
factoryBean.setBeanFactory(beanFactory);
Object entityPathResolver = extractEntityPathResolver(factoryBean);
assertThat(entityPathResolver).isEqualTo(pathResolver);
}
@Test
@Test // DATAJPA-1234
public void withMultipleEntityPathResolversAnExceptionIsThrown() throws Exception {
beans.put("irrelevant", pathResolver);
beans.put("other", new SimpleEntityPathResolver("anotherSuffix"));
factoryBean.setBeanFactory(beanFactory);
factoryBean.setEntityManager(mock(EntityManager.class));
assertThatExceptionOfType(NoUniqueBeanDefinitionException.class) //
.isThrownBy(() -> factoryBean.setBeanFactory(beanFactory));
.isThrownBy(() -> factoryBean.afterPropertiesSet());
}
private Object extractEntityPathResolver(JpaRepositoryFactoryBean<DummyRepository, DummyEntity, Long> factoryBean)
throws Exception {
@SuppressWarnings("unchecked")
private Lazy<EntityPathResolver> extractEntityPathResolver(
JpaRepositoryFactoryBean<DummyRepository, DummyEntity, Long> factoryBean) {
Field pathResolverField = JpaRepositoryFactoryBean.class.getDeclaredField("entityPathResolver");
pathResolverField.setAccessible(true);
return pathResolverField.get(factoryBean);
return (Lazy<EntityPathResolver>) ReflectionTestUtils.getField(factoryBean, "entityPathResolver");
}
static class DummyEntity {}
interface DummyRepository extends Repository<DummyEntity, Long> {}
}