HHH-6174 Making the usage of binder classes more consistent. AnnotationBinder is now differentiating now between pro and post entity binding

This commit is contained in:
Hardy Ferentschik 2011-05-05 15:43:42 +02:00
parent 03d975fdb7
commit 328d72e1cd
5 changed files with 33 additions and 224 deletions

View File

@ -31,6 +31,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.hibernate.metamodel.source.annotations.global.FetchProfileBinder; import org.hibernate.metamodel.source.annotations.global.FetchProfileBinder;
import org.hibernate.metamodel.source.annotations.global.TableBinder;
import org.hibernate.metamodel.source.annotations.util.ConfiguredClassHierarchyBuilder; import org.hibernate.metamodel.source.annotations.util.ConfiguredClassHierarchyBuilder;
import org.hibernate.metamodel.source.internal.MetadataImpl; import org.hibernate.metamodel.source.internal.MetadataImpl;
@ -51,17 +52,22 @@ public class AnnotationBinder {
this.metadata = metadata; this.metadata = metadata;
} }
public void bind(Index annotationIndex) {
preEntityBindings( annotationIndex );
bindMappedClasses( annotationIndex );
postEntityBindings( annotationIndex );
}
/** /**
* Binds global configuration data. This includes mappings which live outside of the configuration for a single * Binds global configuration data prior to entity binding. This includes generators and type definitions
* entity or entity hierarchy, for example sequence generators, fetch profiles, etc
* *
* @param annotationIndex the annotation repository/index * @param annotationIndex the annotation repository/index
*/ */
public void bindGlobalAnnotations(Index annotationIndex) { private void preEntityBindings(Index annotationIndex) {
FetchProfileBinder.bindFetchProfiles( metadata, annotationIndex ); FetchProfileBinder.bind( metadata, annotationIndex );
} }
public void bindMappedClasses(Index annotationIndex) { private void bindMappedClasses(Index annotationIndex) {
// need to order our annotated entities into an order we can process // need to order our annotated entities into an order we can process
Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies( Set<ConfiguredClassHierarchy> hierarchies = ConfiguredClassHierarchyBuilder.createEntityHierarchies(
annotationIndex, metadata.getServiceRegistry() annotationIndex, metadata.getServiceRegistry()
@ -72,212 +78,21 @@ public class AnnotationBinder {
Iterator<ConfiguredClass> iter = hierarchy.iterator(); Iterator<ConfiguredClass> iter = hierarchy.iterator();
while ( iter.hasNext() ) { while ( iter.hasNext() ) {
ConfiguredClass entity = iter.next(); ConfiguredClass entity = iter.next();
bindEntity( entity ); log.info( "Binding entity from annotated class: {}", entity.getName() );
EntityBinder entityBinder = new EntityBinder( metadata, entity );
entityBinder.bind();
} }
} }
} }
public void bindEntity(ConfiguredClass entity) { /**
log.info( "Binding entity from annotated class: {}", entity.getName() ); * Binds global configuration data post entity binding. This includes mappings which live outside of the configuration for a single
EntityBinder entityBinder = new EntityBinder( metadata, entity ); * entity or entity hierarchy, for example sequence generators, fetch profiles, etc
*
// * @param annotationIndex the annotation repository/index
// PersistentClass superEntity = getSuperEntity( */
// clazzToProcess, inheritanceStatePerClass, mappings, inheritanceState private void postEntityBindings(Index annotationIndex) {
// ); TableBinder.bind( metadata, annotationIndex );
//
// PersistentClass persistentClass = makePersistentClass( inheritanceState, superEntity );
// entityBinder.setInheritanceState( inheritanceState );
//
// bindQueries( clazzToProcess, mappings );
// bindFilterDefs( clazzToProcess, mappings );
// bindTypeDefs( clazzToProcess, mappings );
// bindFetchProfiles( clazzToProcess, mappings );
// BinderHelper.bindAnyMetaDefs( clazzToProcess, mappings );
//
// String schema = "";
// String table = ""; //might be no @Table annotation on the annotated class
// String catalog = "";
// List<UniqueConstraintHolder> uniqueConstraints = new ArrayList<UniqueConstraintHolder>();
// if ( clazzToProcess.isAnnotationPresent( javax.persistence.Table.class ) ) {
// javax.persistence.Table tabAnn = clazzToProcess.getAnnotation( javax.persistence.Table.class );
// table = tabAnn.name();
// schema = tabAnn.schema();
// catalog = tabAnn.catalog();
// uniqueConstraints = TableBinder.buildUniqueConstraintHolders( tabAnn.uniqueConstraints() );
// }
//
// Ejb3JoinColumn[] inheritanceJoinedColumns = makeInheritanceJoinColumns(
// clazzToProcess, mappings, inheritanceState, superEntity
// );
// Ejb3DiscriminatorColumn discriminatorColumn = null;
// if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
// discriminatorColumn = processDiscriminatorProperties(
// clazzToProcess, mappings, inheritanceState, entityBinder
// );
// }
//
// entityBinder.setProxy( clazzToProcess.getAnnotation( Proxy.class ) );
// entityBinder.setBatchSize( clazzToProcess.getAnnotation( BatchSize.class ) );
// entityBinder.setWhere( clazzToProcess.getAnnotation( Where.class ) );
// entityBinder.setCache( determineCacheSettings( clazzToProcess, mappings ) );
//
// //Filters are not allowed on subclasses
// if ( !inheritanceState.hasParents() ) {
// bindFilters( clazzToProcess, entityBinder, mappings );
// }
//
// entityBinder.bindEntity();
//
// if ( inheritanceState.hasTable() ) {
// Check checkAnn = clazzToProcess.getAnnotation( Check.class );
// String constraints = checkAnn == null ?
// null :
// checkAnn.constraints();
// entityBinder.bindTable(
// schema, catalog, table, uniqueConstraints,
// constraints, inheritanceState.hasDenormalizedTable() ?
// superEntity.getTable() :
// null
// );
// }
// else {
// if ( clazzToProcess.isAnnotationPresent( Table.class ) ) {
// log.warn(
// "Illegal use of @Table in a subclass of a SINGLE_TABLE hierarchy: " + clazzToProcess
// .getName()
// );
// }
// }
//
// PropertyHolder propertyHolder = PropertyHolderBuilder.buildPropertyHolder(
// clazzToProcess,
// persistentClass,
// entityBinder, mappings, inheritanceStatePerClass
// );
//
// javax.persistence.SecondaryTable secTabAnn = clazzToProcess.getAnnotation(
// javax.persistence.SecondaryTable.class
// );
// javax.persistence.SecondaryTables secTabsAnn = clazzToProcess.getAnnotation(
// javax.persistence.SecondaryTables.class
// );
// entityBinder.firstLevelSecondaryTablesBinding( secTabAnn, secTabsAnn );
//
// OnDelete onDeleteAnn = clazzToProcess.getAnnotation( OnDelete.class );
// boolean onDeleteAppropriate = false;
// if ( InheritanceType.JOINED.equals( inheritanceState.getType() ) && inheritanceState.hasParents() ) {
// onDeleteAppropriate = true;
// final JoinedSubclass jsc = ( JoinedSubclass ) persistentClass;
// if ( persistentClass.getEntityPersisterClass() == null ) {
// persistentClass.getRootClass().setEntityPersisterClass( JoinedSubclassEntityPersister.class );
// }
// SimpleValue key = new DependantValue( mappings, jsc.getTable(), jsc.getIdentifier() );
// jsc.setKey( key );
// ForeignKey fk = clazzToProcess.getAnnotation( ForeignKey.class );
// if ( fk != null && !BinderHelper.isEmptyAnnotationValue( fk.name() ) ) {
// key.setForeignKeyName( fk.name() );
// }
// if ( onDeleteAnn != null ) {
// key.setCascadeDeleteEnabled( OnDeleteAction.CASCADE.equals( onDeleteAnn.action() ) );
// }
// else {
// key.setCascadeDeleteEnabled( false );
// }
// //we are never in a second pass at that stage, so queue it
// SecondPass sp = new JoinedSubclassFkSecondPass( jsc, inheritanceJoinedColumns, key, mappings );
// mappings.addSecondPass( sp );
// mappings.addSecondPass( new CreateKeySecondPass( jsc ) );
//
// }
// else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
// if ( inheritanceState.hasParents() ) {
// if ( persistentClass.getEntityPersisterClass() == null ) {
// persistentClass.getRootClass().setEntityPersisterClass( SingleTableEntityPersister.class );
// }
// }
// else {
// if ( inheritanceState.hasSiblings() || !discriminatorColumn.isImplicit() ) {
// //need a discriminator column
// bindDiscriminatorToPersistentClass(
// (RootClass) persistentClass,
// discriminatorColumn,
// entityBinder.getSecondaryTables(),
// propertyHolder,
// mappings
// );
// entityBinder.bindDiscriminatorValue();//bind it again since the type might have changed
// }
// }
// }
// else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.getType() ) ) {
// if ( inheritanceState.hasParents() ) {
// if ( persistentClass.getEntityPersisterClass() == null ) {
// persistentClass.getRootClass().setEntityPersisterClass( UnionSubclassEntityPersister.class );
// }
// }
// }
// if ( onDeleteAnn != null && !onDeleteAppropriate ) {
// log.warn(
// "Inapropriate use of @OnDelete on entity, annotation ignored: {}", propertyHolder.getEntityName()
// );
// }
//
// // try to find class level generators
// HashMap<String, IdGenerator> classGenerators = buildLocalGenerators( clazzToProcess, mappings );
//
// // check properties
// final InheritanceState.ElementsToProcess elementsToProcess = inheritanceState.getElementsToProcess();
// inheritanceState.postProcess( persistentClass, entityBinder );
//
// final boolean subclassAndSingleTableStrategy = inheritanceState.getType() == InheritanceType.SINGLE_TABLE
// && inheritanceState.hasParents();
// Set<String> idPropertiesIfIdClass = new HashSet<String>();
// boolean isIdClass = mapAsIdClass(
// inheritanceStatePerClass,
// inheritanceState,
// persistentClass,
// entityBinder,
// propertyHolder,
// elementsToProcess,
// idPropertiesIfIdClass,
// mappings
// );
//
// if ( !isIdClass ) {
// entityBinder.setWrapIdsInEmbeddedComponents( elementsToProcess.getIdPropertyCount() > 1 );
// }
//
// processIdPropertiesIfNotAlready(
// inheritanceStatePerClass,
// mappings,
// persistentClass,
// entityBinder,
// propertyHolder,
// classGenerators,
// elementsToProcess,
// subclassAndSingleTableStrategy,
// idPropertiesIfIdClass
// );
//
// if ( !inheritanceState.hasParents() ) {
// final RootClass rootClass = ( RootClass ) persistentClass;
// mappings.addSecondPass( new CreateKeySecondPass( rootClass ) );
// }
// else {
// superEntity.addSubclass( (Subclass) persistentClass );
// }
//
// mappings.addClass( persistentClass );
//
// //Process secondary tables and complementary definitions (ie o.h.a.Table)
// mappings.addSecondPass( new SecondaryTableSecondPass( entityBinder, propertyHolder, clazzToProcess ) );
//
// //add process complementary Table definition (index & all)
// entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Table.class ) );
// entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Tables.class ) );
} }
} }

View File

@ -51,11 +51,15 @@ import org.hibernate.metamodel.source.internal.MetadataImpl;
public class EntityBinder { public class EntityBinder {
private final ConfiguredClass configuredClass; private final ConfiguredClass configuredClass;
private final MetadataImpl meta; private final MetadataImpl meta;
private final Schema.Name schemaName;
private Schema.Name schemaName;
public EntityBinder(MetadataImpl metadata, ConfiguredClass configuredClass) { public EntityBinder(MetadataImpl metadata, ConfiguredClass configuredClass) {
this.configuredClass = configuredClass; this.configuredClass = configuredClass;
this.meta = metadata; this.meta = metadata;
}
public void bind() {
EntityBinding entityBinding = new EntityBinding(); EntityBinding entityBinding = new EntityBinding();
bindJpaEntityAnnotation( entityBinding ); bindJpaEntityAnnotation( entityBinding );
bindHibernateEntityAnnotation( entityBinding ); // optional hibernate specific @org.hibernate.annotations.Entity bindHibernateEntityAnnotation( entityBinding ); // optional hibernate specific @org.hibernate.annotations.Entity
@ -109,15 +113,6 @@ public class EntityBinder {
} }
entityBinding.setBaseTable( table ); entityBinding.setBaseTable( table );
AnnotationInstance hibernateTableAnnotation = JandexHelper.getSingleAnnotation(
configuredClass.getClassInfo(), HibernateDotNames.TABLE
);
if ( hibernateTableAnnotation != null && hibernateTableAnnotation.value( "comment" ) != null ) {
table.addComment( hibernateTableAnnotation.value( "comment" ).asString().trim() );
}
// todo map rest of Hibernate @Table attributes
AnnotationInstance checkAnnotation = JandexHelper.getSingleAnnotation( AnnotationInstance checkAnnotation = JandexHelper.getSingleAnnotation(
configuredClass.getClassInfo(), HibernateDotNames.CHECK configuredClass.getClassInfo(), HibernateDotNames.CHECK
); );

View File

@ -46,7 +46,7 @@ public class FetchProfileBinder {
} }
/** /**
* Binds all {@link org.hibernate.annotations.FetchProfiles} and {@link org.hibernate.annotations.FetchProfile} \ * Binds all {@link org.hibernate.annotations.FetchProfiles} and {@link org.hibernate.annotations.FetchProfile}
* annotations to the specified meta data instance. * annotations to the specified meta data instance.
* *
* @param meta the global metadata * @param meta the global metadata
@ -54,7 +54,7 @@ public class FetchProfileBinder {
*/ */
// TODO how to handle fetch profiles defined in hbm and annotations. Which overrides which? // TODO how to handle fetch profiles defined in hbm and annotations. Which overrides which?
// TODO verify that association exists. See former VerifyFetchProfileReferenceSecondPass // TODO verify that association exists. See former VerifyFetchProfileReferenceSecondPass
public static void bindFetchProfiles(MetadataImpl meta, Index index) { public static void bind(MetadataImpl meta, Index index) {
// check @FetchProfiles // check @FetchProfiles
List<AnnotationInstance> fetchProfilesAnnotations = index.getAnnotations( HibernateDotNames.FETCH_PROFILES ); List<AnnotationInstance> fetchProfilesAnnotations = index.getAnnotations( HibernateDotNames.FETCH_PROFILES );
for ( AnnotationInstance fetchProfilesAnnotation : fetchProfilesAnnotations ) { for ( AnnotationInstance fetchProfilesAnnotation : fetchProfilesAnnotations ) {

View File

@ -130,8 +130,7 @@ public class MetadataImpl implements Metadata, MetadataImplementor, Serializable
// create the annotation binder and pass it the final annotation index // create the annotation binder and pass it the final annotation index
final AnnotationBinder annotationBinder = new AnnotationBinder( this ); final AnnotationBinder annotationBinder = new AnnotationBinder( this );
annotationBinder.bindGlobalAnnotations( index ); annotationBinder.bind( index );
annotationBinder.bindMappedClasses( index );
} }
/** /**

View File

@ -78,7 +78,7 @@ public class FetchProfileBinderTest extends BaseUnitTestCase {
} }
Index index = JandexHelper.indexForClass( service, Foo.class ); Index index = JandexHelper.indexForClass( service, Foo.class );
FetchProfileBinder.bindFetchProfiles( meta, index ); FetchProfileBinder.bind( meta, index );
Iterator<org.hibernate.metamodel.binding.FetchProfile> mappedFetchProfiles = meta.getFetchProfiles().iterator(); Iterator<org.hibernate.metamodel.binding.FetchProfile> mappedFetchProfiles = meta.getFetchProfiles().iterator();
assertTrue( mappedFetchProfiles.hasNext() ); assertTrue( mappedFetchProfiles.hasNext() );
@ -92,7 +92,7 @@ public class FetchProfileBinderTest extends BaseUnitTestCase {
@Test @Test
public void testFetchProfiles() { public void testFetchProfiles() {
Index index = JandexHelper.indexForClass( service, FooBar.class ); Index index = JandexHelper.indexForClass( service, FooBar.class );
FetchProfileBinder.bindFetchProfiles( meta, index ); FetchProfileBinder.bind( meta, index );
Iterator<org.hibernate.metamodel.binding.FetchProfile> mappedFetchProfiles = meta.getFetchProfiles().iterator(); Iterator<org.hibernate.metamodel.binding.FetchProfile> mappedFetchProfiles = meta.getFetchProfiles().iterator();
assertTrue( mappedFetchProfiles.hasNext() ); assertTrue( mappedFetchProfiles.hasNext() );
@ -129,7 +129,7 @@ public class FetchProfileBinderTest extends BaseUnitTestCase {
} }
Index index = JandexHelper.indexForClass( service, Foo.class ); Index index = JandexHelper.indexForClass( service, Foo.class );
FetchProfileBinder.bindFetchProfiles( meta, index ); FetchProfileBinder.bind( meta, index );
} }
@FetchProfiles( { @FetchProfiles( {