diff --git a/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryBean.java b/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryBean.java index 8ebeb852e..b18a45e62 100644 --- a/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryBean.java +++ b/src/main/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryBean.java @@ -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, S, ID> extends TransactionalRepositoryFactoryBeanSupport { private @Nullable EntityManager entityManager; - private EntityPathResolver entityPathResolver = SimpleEntityPathResolver.INSTANCE; + private Lazy entityPathResolver = Lazy.of(SimpleEntityPathResolver.INSTANCE); /** * Creates a new {@link JpaRepositoryFactoryBean} for the given repository interface. @@ -78,9 +77,7 @@ public class JpaRepositoryFactoryBean, 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, 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, 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 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'" // - ); - }); - } - } - } diff --git a/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryBeanEntityPathResolverUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryBeanEntityPathResolverUnitTests.java index 9699f2bec..4e7b8396c 100644 --- a/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryBeanEntityPathResolverUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/support/JpaRepositoryFactoryBeanEntityPathResolverUnitTests.java @@ -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 factoryBean) - throws Exception { + @SuppressWarnings("unchecked") + private Lazy extractEntityPathResolver( + JpaRepositoryFactoryBean factoryBean) { - Field pathResolverField = JpaRepositoryFactoryBean.class.getDeclaredField("entityPathResolver"); - pathResolverField.setAccessible(true); - return pathResolverField.get(factoryBean); + return (Lazy) ReflectionTestUtils.getField(factoryBean, "entityPathResolver"); } static class DummyEntity {} interface DummyRepository extends Repository {} - }