HHH-6589 - Skip non-JPA features populating JPA "static metamodel"

This commit is contained in:
Steve Ebersole 2012-03-02 09:25:30 -06:00 committed by Steve Ebersole
parent f4c9b284a1
commit f26435dfec
5 changed files with 108 additions and 19 deletions

View File

@ -312,6 +312,31 @@ public class AvailableSettings {
*/
public static final String ENTITY_MANAGER_FACTORY_NAME = "hibernate.ejb.entitymanager_factory_name";
/**
* @deprecated use {@link #JPA_METAMODEL_POPULATION} instead.
*/
@Deprecated
public static final String JPA_METAMODEL_GENERATION = "hibernate.ejb.metamodel.generation";
/**
* Setting that controls whether we seek out JPA "static metamodel" classes and populate them. Accepts
* 3 values:<ul>
* <li>
* <b>enabled</b> - Do the population
* </li>
* <li>
* <b>disabled</b> - Do not do the population
* </li>
* <li>
* <b>ignoreUnsupported</b> - Do the population, but ignore any non-JPA features that would otherwise
* result in the population failing.
* </li>
* </ul>
*
*/
public static final String JPA_METAMODEL_POPULATION = "hibernate.ejb.metamodel.population";
/**
* List of classes names
* Internal use only

View File

@ -41,6 +41,8 @@ import javax.persistence.metamodel.Metamodel;
import javax.persistence.spi.LoadState;
import javax.persistence.spi.PersistenceUnitTransactionType;
import org.jboss.logging.Logger;
import org.hibernate.Hibernate;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
@ -51,6 +53,7 @@ import org.hibernate.ejb.util.PersistenceUtilHelper;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.UUIDGenerator;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.service.ServiceRegistry;
@ -65,6 +68,9 @@ import org.hibernate.service.ServiceRegistry;
public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
private static final long serialVersionUID = 5423543L;
private static final IdentifierGenerator UUID_GENERATOR = UUIDGenerator.buildSessionFactoryUniqueIdentifierGenerator();
private static final Logger log = Logger.getLogger( EntityManagerFactoryImpl.class );
private final transient SessionFactory sessionFactory;
private final transient PersistenceUnitTransactionType transactionType;
private final transient boolean discardOnClose;
@ -90,15 +96,16 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
this.discardOnClose = discardOnClose;
this.sessionInterceptorClass = sessionInterceptorClass;
final Iterator<PersistentClass> classes = cfg.getClassMappings();
//a safe guard till we are confident that metamodel is well tested
// disabled: dont create metamodel
// ignoreUnsupported: create metamodel, but ignore unsupported/unknown annotations (like @Any) HHH-6589
final String ejbMetamodelGenerationProperty = cfg.getProperty( "hibernate.ejb.metamodel.generation" );
if ( !"disabled".equalsIgnoreCase( ejbMetamodelGenerationProperty ) ) {
this.metamodel = MetamodelImpl.buildMetamodel( classes, ( SessionFactoryImplementor ) sessionFactory, "ignoreUnsupported".equalsIgnoreCase( ejbMetamodelGenerationProperty ));
final JpaMetaModelPopulationSetting jpaMetaModelPopulationSetting = determineJpaMetaModelPopulationSetting( cfg );
if ( JpaMetaModelPopulationSetting.DISABLED == jpaMetaModelPopulationSetting ) {
this.metamodel = null;
}
else {
this.metamodel = null;
this.metamodel = MetamodelImpl.buildMetamodel(
classes,
( SessionFactoryImplementor ) sessionFactory,
JpaMetaModelPopulationSetting.IGNORE_UNSUPPORTED == jpaMetaModelPopulationSetting
);
}
this.criteriaBuilder = new CriteriaBuilderImpl( this );
this.util = new HibernatePersistenceUnitUtil( this );
@ -117,6 +124,43 @@ public class EntityManagerFactoryImpl implements HibernateEntityManagerFactory {
this.entityManagerFactoryName = entityManagerFactoryName;
EntityManagerFactoryRegistry.INSTANCE.addEntityManagerFactory(entityManagerFactoryName, this);
}
private enum JpaMetaModelPopulationSetting {
ENABLED,
DISABLED,
IGNORE_UNSUPPORTED;
private static JpaMetaModelPopulationSetting parse(String setting) {
if ( "enabled".equalsIgnoreCase( setting ) ) {
return ENABLED;
}
else if ( "disabled".equalsIgnoreCase( setting ) ) {
return DISABLED;
}
else {
return IGNORE_UNSUPPORTED;
}
}
}
protected JpaMetaModelPopulationSetting determineJpaMetaModelPopulationSetting(Configuration cfg) {
String setting = ConfigurationHelper.getString(
AvailableSettings.JPA_METAMODEL_POPULATION,
cfg.getProperties(),
null
);
if ( setting == null ) {
setting = ConfigurationHelper.getString( AvailableSettings.JPA_METAMODEL_GENERATION, cfg.getProperties(), null );
if ( setting != null ) {
log.infof(
"Encountered deprecated setting [%s], use [%s] instead",
AvailableSettings.JPA_METAMODEL_GENERATION,
AvailableSettings.JPA_METAMODEL_POPULATION
);
}
}
return JpaMetaModelPopulationSetting.parse( setting );
}
private static void addAll(HashMap<String, Object> propertyMap, Properties properties) {
for ( Map.Entry entry : properties.entrySet() ) {

View File

@ -83,20 +83,36 @@ public class AttributeFactory {
public <X, Y> AttributeImplementor<X, Y> buildAttribute(AbstractManagedType<X> ownerType, Property property) {
if ( property.isSynthetic() ) {
// hide synthetic/virtual properties (fabricated by Hibernate) from the JPA metamodel.
LOG.trace("Skipping synthetic property " + ownerType.getJavaType().getName() + "(" + property.getName() + ")");
LOG.tracef(
"Skipping synthetic property %s(%s)",
ownerType.getJavaType().getName(),
property.getName()
);
return null;
}
LOG.trace("Building attribute [" + ownerType.getJavaType().getName() + "." + property.getName() + "]");
final AttributeContext<X> attributeContext = wrap( ownerType, property );
final AttributeMetadata<X,Y> attributeMetadata =
determineAttributeMetadata( attributeContext, NORMAL_MEMBER_RESOLVER );
if (attributeMetadata == null) return null;
if (attributeMetadata.isPlural()) return buildPluralAttribute((PluralAttributeMetadata)attributeMetadata);
if (attributeMetadata == null) {
return null;
}
if (attributeMetadata.isPlural()) {
return buildPluralAttribute((PluralAttributeMetadata)attributeMetadata);
}
final SingularAttributeMetadata<X, Y> singularAttributeMetadata = (SingularAttributeMetadata<X, Y>)attributeMetadata;
final Type<Y> metaModelType = getMetaModelType(singularAttributeMetadata.getValueContext());
return new SingularAttributeImpl<X, Y>(attributeMetadata.getName(), attributeMetadata.getJavaType(), ownerType,
attributeMetadata.getMember(), false, false, property.isOptional(), metaModelType,
attributeMetadata.getPersistentAttributeType());
return new SingularAttributeImpl<X, Y>(
attributeMetadata.getName(),
attributeMetadata.getJavaType(),
ownerType,
attributeMetadata.getMember(),
false,
false,
property.isOptional(),
metaModelType,
attributeMetadata.getPersistentAttributeType()
);
}
private <X> AttributeContext<X> wrap(final AbstractManagedType<X> ownerType, final Property property) {
@ -428,11 +444,12 @@ public class AttributeFactory {
LOG.trace(" Determined type [name=" + type.getName() + ", class=" + type.getClass().getName() + "]");
if ( type.isAnyType() ) {
// ANY mappings are currently not supported in the JPA metamodel; see HHH-6589
if ( context.isIgnoreUnsupported() ) {
// HHH-6589 Support "Any" mappings when building metamodel
return null;
} else {
throw new UnsupportedOperationException( "any not supported yet" );
}
else {
throw new UnsupportedOperationException( "ANY not supported" );
}
}
else if ( type.isAssociationType() ) {

View File

@ -48,9 +48,12 @@ 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 sessionFactory The Hibernate session factry.
* @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
public static MetamodelImpl buildMetamodel(
Iterator<PersistentClass> persistentClasses,
SessionFactoryImplementor sessionFactory) {
@ -62,7 +65,7 @@ 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 sessionFactory The Hibernate session factry.
* @param sessionFactory The Hibernate session factory.
* @param ignoreUnsupported ignore unsupported/unknown annotations (like @Any)
* @return The built metamodel
*/

View File

@ -73,7 +73,7 @@ public class MetadataTest extends BaseEntityManagerFunctionalTestCase {
cfg.addAnnotatedClass( WithGenericCollection.class );
cfg.buildMappings();
SessionFactoryImplementor sfi = (SessionFactoryImplementor) cfg.buildSessionFactory( serviceRegistry() );
MetamodelImpl.buildMetamodel( cfg.getClassMappings(), sfi );
MetamodelImpl.buildMetamodel( cfg.getClassMappings(), sfi, true );
}
@Test