HHH-8534 - Metamodel#managedType(SomeMappedSuperclass.class) returns null
This commit is contained in:
parent
a1ff3a29cb
commit
2bb866a616
|
@ -404,6 +404,17 @@ public class Configuration implements Serializable {
|
|||
return mappedSuperClasses.values().iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a copy of all known MappedSuperclasses
|
||||
* <p/>
|
||||
* EXPERIMENTAL Consider this API as PRIVATE
|
||||
*
|
||||
* @return Set of all known MappedSuperclasses
|
||||
*/
|
||||
public java.util.Set<MappedSuperclass> getMappedSuperclassMappingsCopy() {
|
||||
return new HashSet<MappedSuperclass>( mappedSuperClasses.values() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mapping for a particular entity
|
||||
*
|
||||
|
|
|
@ -141,14 +141,14 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
|
|||
this.discardOnClose = settings.isReleaseResourcesOnCloseEnabled();
|
||||
this.sessionInterceptorClass = settings.getSessionInterceptorClass();
|
||||
|
||||
final Iterator<PersistentClass> classes = cfg.getClassMappings();
|
||||
final JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting = determineJpaMetaModelPopulationSetting( cfg );
|
||||
if ( JpaMetaModelPopulationSetting.DISABLED == jpaMetaModelPopulationSetting ) {
|
||||
this.metamodel = null;
|
||||
}
|
||||
else {
|
||||
this.metamodel = MetamodelImpl.buildMetamodel(
|
||||
classes,
|
||||
cfg.getClassMappings(),
|
||||
cfg.getMappedSuperclassMappingsCopy(),
|
||||
sessionFactory,
|
||||
JpaMetaModelPopulationSetting.IGNORE_UNSUPPORTED == jpaMetaModelPopulationSetting
|
||||
);
|
||||
|
|
|
@ -117,4 +117,11 @@ public interface EntityManagerMessageLogger extends CoreMessageLogger {
|
|||
id = 15014
|
||||
)
|
||||
void deprecatedJpaPositionalParameterAccess(Integer jpaPositionalParameter);
|
||||
|
||||
@LogMessage( level = INFO )
|
||||
@Message(
|
||||
id = 15015,
|
||||
value = "Encountered a MappedSuperclass [%s] not used in any entity hierarchy"
|
||||
)
|
||||
void unusedMappedSuperclass(String name);
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ class MetadataContext {
|
|||
MetadataContext.class.getName());
|
||||
|
||||
private final SessionFactoryImplementor sessionFactory;
|
||||
private Set<MappedSuperclass> knownMappedSuperclasses;
|
||||
private final boolean ignoreUnsupported;
|
||||
private final AttributeFactory attributeFactory = new AttributeFactory( this );
|
||||
|
||||
|
@ -92,8 +93,12 @@ class MetadataContext {
|
|||
private Map<MappedSuperclassTypeImpl<?>, PersistentClass> mappedSuperClassTypeToPersistentClass
|
||||
= new HashMap<MappedSuperclassTypeImpl<?>, PersistentClass>();
|
||||
|
||||
public MetadataContext(SessionFactoryImplementor sessionFactory, boolean ignoreUnsupported) {
|
||||
public MetadataContext(
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
Set<MappedSuperclass> mappedSuperclasses,
|
||||
boolean ignoreUnsupported) {
|
||||
this.sessionFactory = sessionFactory;
|
||||
this.knownMappedSuperclasses = mappedSuperclasses;
|
||||
this.ignoreUnsupported = ignoreUnsupported;
|
||||
}
|
||||
|
||||
|
@ -145,11 +150,14 @@ class MetadataContext {
|
|||
embeddables.put( embeddableType.getJavaType(), embeddableType );
|
||||
}
|
||||
|
||||
/*package*/ void registerMappedSuperclassType(MappedSuperclass mappedSuperclass,
|
||||
/*package*/ void registerMappedSuperclassType(
|
||||
MappedSuperclass mappedSuperclass,
|
||||
MappedSuperclassTypeImpl<?> mappedSuperclassType) {
|
||||
mappedSuperclassByMappedSuperclassMapping.put( mappedSuperclass, mappedSuperclassType );
|
||||
orderedMappings.add( mappedSuperclass );
|
||||
mappedSuperClassTypeToPersistentClass.put( mappedSuperclassType, getEntityWorkedOn() );
|
||||
|
||||
knownMappedSuperclasses.remove( mappedSuperclass );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -192,6 +200,7 @@ class MetadataContext {
|
|||
@SuppressWarnings({ "unchecked" })
|
||||
public void wrapUp() {
|
||||
LOG.trace("Wrapping up metadata context...");
|
||||
|
||||
//we need to process types from superclasses to subclasses
|
||||
for (Object mapping : orderedMappings) {
|
||||
if ( PersistentClass.class.isAssignableFrom( mapping.getClass() ) ) {
|
||||
|
@ -490,4 +499,8 @@ class MetadataContext {
|
|||
}
|
||||
return persistentClass;
|
||||
}
|
||||
|
||||
public Set<MappedSuperclass> getUnusedMappedSuperclasses() {
|
||||
return new HashSet<MappedSuperclass>( knownMappedSuperclasses );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,17 +21,26 @@
|
|||
*/
|
||||
package org.hibernate.jpa.internal.metamodel;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.mapping.MappedSuperclass;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
|
||||
import javax.persistence.metamodel.EmbeddableType;
|
||||
import javax.persistence.metamodel.EntityType;
|
||||
import javax.persistence.metamodel.ManagedType;
|
||||
import javax.persistence.metamodel.MappedSuperclassType;
|
||||
import javax.persistence.metamodel.Metamodel;
|
||||
import java.io.Serializable;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.persistence.metamodel.*;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.internal.util.collections.CollectionHelper;
|
||||
import org.hibernate.jpa.internal.EntityManagerMessageLogger;
|
||||
import org.hibernate.jpa.internal.HEMLogging;
|
||||
import org.hibernate.mapping.MappedSuperclass;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
|
||||
/**
|
||||
* Hibernate implementation of the JPA {@link Metamodel} contract.
|
||||
|
@ -40,6 +49,8 @@ import javax.persistence.metamodel.*;
|
|||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class MetamodelImpl implements Metamodel, Serializable {
|
||||
private static final EntityManagerMessageLogger log = HEMLogging.messageLogger( MetamodelImpl.class );
|
||||
|
||||
private final Map<Class<?>,EntityTypeImpl<?>> entities;
|
||||
private final Map<Class<?>, EmbeddableTypeImpl<?>> embeddables;
|
||||
private final Map<Class<?>, MappedSuperclassType<?>> mappedSuperclassTypeMap;
|
||||
|
@ -53,13 +64,13 @@ public class MetamodelImpl implements Metamodel, Serializable {
|
|||
* @param sessionFactory The Hibernate session factory.
|
||||
* @return The built metamodel
|
||||
*
|
||||
* @deprecated use {@link #buildMetamodel(java.util.Iterator,org.hibernate.engine.spi.SessionFactoryImplementor,boolean)} instead
|
||||
* @deprecated use {@link #buildMetamodel(Iterator,Set,SessionFactoryImplementor,boolean)} instead
|
||||
*/
|
||||
@Deprecated
|
||||
public static MetamodelImpl buildMetamodel(
|
||||
Iterator<PersistentClass> persistentClasses,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
return buildMetamodel(persistentClasses, sessionFactory, false);
|
||||
return buildMetamodel( persistentClasses, Collections.<MappedSuperclass>emptySet(), sessionFactory, false );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,23 +78,37 @@ public class MetamodelImpl implements Metamodel, Serializable {
|
|||
* {@link PersistentClass} models as well as the Hibernate {@link org.hibernate.SessionFactory}.
|
||||
*
|
||||
* @param persistentClasses Iterator over the Hibernate (config-time) metamodel
|
||||
* @param mappedSuperclasses All known MappedSuperclasses
|
||||
* @param sessionFactory The Hibernate session factory.
|
||||
* @param ignoreUnsupported ignore unsupported/unknown annotations (like @Any)
|
||||
*
|
||||
* @return The built metamodel
|
||||
*/
|
||||
public static MetamodelImpl buildMetamodel(
|
||||
Iterator<PersistentClass> persistentClasses,
|
||||
Set<MappedSuperclass> mappedSuperclasses,
|
||||
SessionFactoryImplementor sessionFactory,
|
||||
boolean ignoreUnsupported) {
|
||||
MetadataContext context = new MetadataContext( sessionFactory, ignoreUnsupported );
|
||||
MetadataContext context = new MetadataContext( sessionFactory, mappedSuperclasses, ignoreUnsupported );
|
||||
while ( persistentClasses.hasNext() ) {
|
||||
PersistentClass pc = persistentClasses.next();
|
||||
locateOrBuildEntityType( pc, context );
|
||||
}
|
||||
handleUnusedMappedSuperclasses( context );
|
||||
context.wrapUp();
|
||||
return new MetamodelImpl( context.getEntityTypeMap(), context.getEmbeddableTypeMap(), context.getMappedSuperclassTypeMap(), context.getEntityTypesByEntityName() );
|
||||
}
|
||||
|
||||
private static void handleUnusedMappedSuperclasses(MetadataContext context) {
|
||||
final Set<MappedSuperclass> unusedMappedSuperclasses = context.getUnusedMappedSuperclasses();
|
||||
if ( !unusedMappedSuperclasses.isEmpty() ) {
|
||||
for ( MappedSuperclass mappedSuperclass : unusedMappedSuperclasses ) {
|
||||
log.unusedMappedSuperclass( mappedSuperclass.getMappedClass().getName() );
|
||||
locateOrBuildMappedsuperclassType( mappedSuperclass, context );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static EntityTypeImpl<?> locateOrBuildEntityType(PersistentClass persistentClass, MetadataContext context) {
|
||||
EntityTypeImpl<?> entityType = context.locateEntityType( persistentClass );
|
||||
if ( entityType == null ) {
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
*/
|
||||
package org.hibernate.jpa.test.metadata;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.metamodel.Attribute;
|
||||
|
@ -45,6 +46,7 @@ import org.hibernate.cfg.Configuration;
|
|||
import org.hibernate.jpa.internal.metamodel.MetamodelImpl;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.mapping.MappedSuperclass;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
@ -108,7 +110,7 @@ public class MetadataTest extends BaseEntityManagerFunctionalTestCase {
|
|||
cfg.addAnnotatedClass( WithGenericCollection.class );
|
||||
cfg.buildMappings();
|
||||
SessionFactoryImplementor sfi = (SessionFactoryImplementor) cfg.buildSessionFactory( serviceRegistry() );
|
||||
MetamodelImpl.buildMetamodel( cfg.getClassMappings(), sfi, true );
|
||||
MetamodelImpl.buildMetamodel( cfg.getClassMappings(), Collections.<MappedSuperclass>emptySet(), sfi, true );
|
||||
sfi.close();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.jpa.test.metamodel;
|
||||
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.metamodel.ManagedType;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.jpa.boot.spi.Bootstrap;
|
||||
import org.hibernate.jpa.test.PersistenceUnitDescriptorAdapter;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.FailureExpected;
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
/**
|
||||
* Specifically see if we can access a MappedSuperclass via Metamodel that is not part of a entity hierarchy
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class MappedSuperclassType2Test extends BaseUnitTestCase {
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-8534" )
|
||||
@FailureExpected( jiraKey = "HHH-8534" )
|
||||
public void testMappedSuperclassAccessNoEntity() {
|
||||
// stupid? yes. tck does it? yes.
|
||||
|
||||
final PersistenceUnitDescriptorAdapter pu = new PersistenceUnitDescriptorAdapter() {
|
||||
@Override
|
||||
public List<String> getManagedClassNames() {
|
||||
// pass in a MappedSuperclass that is not used in any entity hierarchy
|
||||
return Arrays.asList( SomeMappedSuperclass.class.getName() );
|
||||
}
|
||||
};
|
||||
|
||||
final Map settings = new HashMap();
|
||||
settings.put( AvailableSettings.HBM2DDL_AUTO, "create-drop" );
|
||||
|
||||
EntityManagerFactory emf = Bootstrap.getEntityManagerFactoryBuilder( pu, settings ).build();
|
||||
try {
|
||||
ManagedType<SomeMappedSuperclass> type = emf.getMetamodel().managedType( SomeMappedSuperclass.class );
|
||||
// the issue was in regards to throwing an exception, but also check for nullness
|
||||
assertNotNull( type );
|
||||
}
|
||||
finally {
|
||||
emf.close();
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue