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:
parent
03d975fdb7
commit
328d72e1cd
|
@ -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 ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
);
|
);
|
||||||
|
|
|
@ -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 ) {
|
||||||
|
|
|
@ -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 );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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( {
|
||||||
|
|
Loading…
Reference in New Issue