diff --git a/src/main/java/org/springframework/data/jpa/mapping/JpaMetamodelMappingContext.java b/src/main/java/org/springframework/data/jpa/mapping/JpaMetamodelMappingContext.java index 8c9a3177c..f60da8f5e 100644 --- a/src/main/java/org/springframework/data/jpa/mapping/JpaMetamodelMappingContext.java +++ b/src/main/java/org/springframework/data/jpa/mapping/JpaMetamodelMappingContext.java @@ -63,7 +63,10 @@ public class JpaMetamodelMappingContext */ @Override protected JpaPersistentEntityImpl createPersistentEntity(TypeInformation typeInformation) { - return new JpaPersistentEntityImpl(typeInformation, persistenceProvider); + + Metamodel metamodel = getMetamodelFor(typeInformation.getType()); + + return new JpaPersistentEntityImpl(typeInformation, persistenceProvider, metamodel); } /* @@ -73,14 +76,7 @@ public class JpaMetamodelMappingContext @Override protected JpaPersistentProperty createPersistentProperty(Property property, JpaPersistentEntityImpl owner, SimpleTypeHolder simpleTypeHolder) { - - Metamodel metamodel = getMetamodelFor(owner.getType()); - - if (metamodel == null) { - throw new IllegalStateException(String.format("Metamodel for %s not available!", owner.getType())); - } - - return new JpaPersistentPropertyImpl(metamodel, property, owner, simpleTypeHolder); + return new JpaPersistentPropertyImpl(owner.getMetamodel(), property, owner, simpleTypeHolder); } /* diff --git a/src/main/java/org/springframework/data/jpa/mapping/JpaPersistentEntityImpl.java b/src/main/java/org/springframework/data/jpa/mapping/JpaPersistentEntityImpl.java index f3a0f25cd..44a1d02b5 100644 --- a/src/main/java/org/springframework/data/jpa/mapping/JpaPersistentEntityImpl.java +++ b/src/main/java/org/springframework/data/jpa/mapping/JpaPersistentEntityImpl.java @@ -17,6 +17,8 @@ package org.springframework.data.jpa.mapping; import java.util.Comparator; +import javax.persistence.metamodel.Metamodel; + import org.springframework.data.annotation.Version; import org.springframework.data.jpa.provider.ProxyIdAccessor; import org.springframework.data.mapping.IdentifierAccessor; @@ -43,6 +45,7 @@ class JpaPersistentEntityImpl extends BasicPersistentEntity extends BasicPersistentEntity information, ProxyIdAccessor proxyIdAccessor) { + public JpaPersistentEntityImpl(TypeInformation information, ProxyIdAccessor proxyIdAccessor, Metamodel metamodel) { super(information, null); Assert.notNull(proxyIdAccessor, "ProxyIdAccessor must not be null!"); this.proxyIdAccessor = proxyIdAccessor; + this.metamodel = metamodel; } /* @@ -92,6 +96,10 @@ class JpaPersistentEntityImpl extends BasicPersistentEntity extends BasicPersistentEntity entity, Object bean, - ProxyIdAccessor proxyIdAccessor) { + JpaProxyAwareIdentifierAccessor(JpaPersistentEntity entity, Object bean, ProxyIdAccessor proxyIdAccessor) { super(entity, bean); diff --git a/src/main/java/org/springframework/data/jpa/repository/config/JpaMetamodelMappingContextFactoryBean.java b/src/main/java/org/springframework/data/jpa/repository/config/JpaMetamodelMappingContextFactoryBean.java index fd6c42164..f108047f2 100644 --- a/src/main/java/org/springframework/data/jpa/repository/config/JpaMetamodelMappingContextFactoryBean.java +++ b/src/main/java/org/springframework/data/jpa/repository/config/JpaMetamodelMappingContextFactoryBean.java @@ -16,13 +16,13 @@ package org.springframework.data.jpa.repository.config; import java.util.Collection; -import java.util.HashSet; import java.util.Set; import javax.persistence.EntityManagerFactory; -import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.Metamodel; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.FactoryBean; @@ -31,6 +31,7 @@ import org.springframework.beans.factory.config.AbstractFactoryBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext; +import org.springframework.data.util.StreamUtils; import org.springframework.lang.Nullable; /** @@ -43,6 +44,8 @@ import org.springframework.lang.Nullable; class JpaMetamodelMappingContextFactoryBean extends AbstractFactoryBean implements ApplicationContextAware { + private static final Logger LOG = LoggerFactory.getLogger(JpaMetamodelMappingContextFactoryBean.class); + private @Nullable ListableBeanFactory beanFactory; /* @@ -70,25 +73,17 @@ class JpaMetamodelMappingContextFactoryBean extends AbstractFactoryBean models = getMetamodels(); - Set> entitySources = new HashSet>(); - - for (Metamodel metamodel : models) { - - for (ManagedType type : metamodel.getManagedTypes()) { - - Class javaType = type.getJavaType(); - - if (javaType != null) { - entitySources.add(javaType); - } - } + if (LOG.isDebugEnabled()) { + LOG.debug("Initializing JpaMetamodelMappingContext…"); } - JpaMetamodelMappingContext context = new JpaMetamodelMappingContext(models); - context.setInitialEntitySet(entitySources); + JpaMetamodelMappingContext context = new JpaMetamodelMappingContext(getMetamodels()); context.initialize(); + if (LOG.isDebugEnabled()) { + LOG.debug("Finished initializing JpaMetamodelMappingContext!"); + } + return context; } @@ -105,12 +100,9 @@ class JpaMetamodelMappingContextFactoryBean extends AbstractFactoryBean factories = BeanFactoryUtils .beansOfTypeIncludingAncestors(beanFactory, EntityManagerFactory.class).values(); - Set metamodels = new HashSet(factories.size()); - for (EntityManagerFactory emf : factories) { - metamodels.add(emf.getMetamodel()); - } - - return metamodels; + return factories.stream() // + .map(EntityManagerFactory::getMetamodel) // + .collect(StreamUtils.toUnmodifiableSet()); } } diff --git a/src/main/java/org/springframework/data/jpa/util/JpaMetamodel.java b/src/main/java/org/springframework/data/jpa/util/JpaMetamodel.java index 3b3ee202e..912158b17 100644 --- a/src/main/java/org/springframework/data/jpa/util/JpaMetamodel.java +++ b/src/main/java/org/springframework/data/jpa/util/JpaMetamodel.java @@ -16,16 +16,15 @@ package org.springframework.data.jpa.util; import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; import java.util.Optional; -import java.util.Set; import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.Metamodel; import javax.persistence.metamodel.SingularAttribute; +import org.springframework.data.util.Lazy; +import org.springframework.data.util.StreamUtils; import org.springframework.util.Assert; /** @@ -38,7 +37,7 @@ public class JpaMetamodel { private final Metamodel metamodel; - private Optional>> managedTypes = Optional.empty(); + private Lazy>> managedTypes; /** * Creates a new {@link JpaMetamodel} for the given JPA {@link Metamodel}. @@ -50,6 +49,10 @@ public class JpaMetamodel { Assert.notNull(metamodel, "Metamodel must not be null!"); this.metamodel = metamodel; + this.managedTypes = Lazy.of(() -> metamodel.getManagedTypes().stream() // + .map(ManagedType::getJavaType) // + .filter(it -> it != null) // + .collect(StreamUtils.toUnmodifiableSet())); } /** @@ -62,7 +65,7 @@ public class JpaMetamodel { Assert.notNull(type, "Type must not be null!"); - return getManagedTypes().contains(type); + return managedTypes.get().contains(type); } /** @@ -84,35 +87,6 @@ public class JpaMetamodel { .orElse(false); } - /** - * Returns all types managed by the backing {@link Metamodel}. Skips {@link ManagedType} instances that return - * {@literal null} for calls to {@link ManagedType#getJavaType()}. - * - * @return all managed types. - * @see HHH-10968 - */ - private Collection> getManagedTypes() { - - if (!managedTypes.isPresent()) { - - Set> managedTypes = metamodel.getManagedTypes(); - Set> types = new HashSet>(managedTypes.size()); - - for (ManagedType managedType : metamodel.getManagedTypes()) { - - Class type = managedType.getJavaType(); - - if (type != null) { - types.add(type); - } - } - - this.managedTypes = Optional.of(Collections.unmodifiableSet(types)); - } - - return this.managedTypes.get(); - } - /** * Returns the {@link SingularAttribute} representing the identifier of the given {@link EntityType} if it contains a * singular one. diff --git a/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtensionUnitTests.java b/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtensionUnitTests.java index 4570dac4d..2ab5c21c4 100644 --- a/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtensionUnitTests.java +++ b/src/test/java/org/springframework/data/jpa/repository/config/JpaRepositoryConfigExtensionUnitTests.java @@ -22,10 +22,8 @@ import static org.mockito.Mockito.*; import java.util.Arrays; import java.util.Collections; -import java.util.Set; import javax.persistence.EntityManagerFactory; -import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.Metamodel; import org.junit.Rule; @@ -100,13 +98,9 @@ public class JpaRepositoryConfigExtensionUnitTests { ApplicationContext context = mock(ApplicationContext.class); EntityManagerFactory emf = mock(EntityManagerFactory.class); Metamodel metamodel = mock(Metamodel.class); - ManagedType managedType = mock(ManagedType.class); - - Set> managedTypes = Collections.> singleton(managedType); when(context.getBeansOfType(EntityManagerFactory.class)).thenReturn(Collections.singletonMap("emf", emf)); when(emf.getMetamodel()).thenReturn(metamodel); - when(metamodel.getManagedTypes()).thenReturn(managedTypes); JpaMetamodelMappingContextFactoryBean factoryBean = new JpaMetamodelMappingContextFactoryBean(); factoryBean.setApplicationContext(context);