HHH-4527
No functional changes yet. Just some cleanup and refactoring (extract method, encapsulate field) git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18211 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
b95147a81e
commit
025b3cc141
|
@ -23,17 +23,20 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.annotations;
|
package org.hibernate.annotations;
|
||||||
|
|
||||||
import static java.lang.annotation.ElementType.*;
|
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.FIELD;
|
||||||
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
|
import static java.lang.annotation.ElementType.TYPE;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Property Access type
|
* Property Access type
|
||||||
*
|
*
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
*/
|
*/
|
||||||
@Target({TYPE, METHOD, FIELD})
|
@Target({ TYPE, METHOD, FIELD })
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
public @interface AccessType {
|
public @interface AccessType {
|
||||||
String value();
|
String value();
|
||||||
|
|
|
@ -176,6 +176,7 @@ import org.slf4j.LoggerFactory;
|
||||||
* package)
|
* package)
|
||||||
*
|
*
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
|
* @author Hardy Ferentschik
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public final class AnnotationBinder {
|
public final class AnnotationBinder {
|
||||||
|
@ -247,7 +248,7 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void bindPackage(String packageName, ExtendedMappings mappings) {
|
public static void bindPackage(String packageName, ExtendedMappings mappings) {
|
||||||
XPackage pckg = null;
|
XPackage pckg;
|
||||||
try {
|
try {
|
||||||
pckg = mappings.getReflectionManager().packageForName( packageName );
|
pckg = mappings.getReflectionManager().packageForName( packageName );
|
||||||
}
|
}
|
||||||
|
@ -438,153 +439,72 @@ public final class AnnotationBinder {
|
||||||
bindFilterDefs(clazzToProcess, mappings);
|
bindFilterDefs(clazzToProcess, mappings);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( AnnotatedClassType.EMBEDDABLE_SUPERCLASS.equals( classType ) //will be processed by their subentities
|
if( !isEntityClassType( clazzToProcess, classType ) ) {
|
||||||
|| AnnotatedClassType.NONE.equals( classType ) //to be ignored
|
|
||||||
|| AnnotatedClassType.EMBEDDABLE.equals( classType ) //allow embeddable element declaration
|
|
||||||
) {
|
|
||||||
if ( AnnotatedClassType.NONE.equals( classType )
|
|
||||||
&& clazzToProcess.isAnnotationPresent( org.hibernate.annotations.Entity.class ) ) {
|
|
||||||
log.warn( "Class annotated @org.hibernate.annotations.Entity but not javax.persistence.Entity "
|
|
||||||
+ "(most likely a user error): {}", clazzToProcess.getName() );
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ( !classType.equals( AnnotatedClassType.ENTITY ) ) {
|
|
||||||
//TODO make this test accurate by removing the none elements artifically added
|
|
||||||
throw new AnnotationException(
|
|
||||||
"Annotated class should have a @javax.persistence.Entity, @javax.persistence.Embeddable or @javax.persistence.EmbeddedSuperclass annotation: " + clazzToProcess
|
|
||||||
.getName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
XAnnotatedElement annotatedClass = clazzToProcess;
|
|
||||||
log.info( "Binding entity from annotated class: {}", clazzToProcess.getName() );
|
log.info( "Binding entity from annotated class: {}", clazzToProcess.getName() );
|
||||||
final ReflectionManager reflectionManager = mappings.getReflectionManager();
|
|
||||||
InheritanceState superEntityState =
|
PersistentClass superEntity = getSuperEntity(clazzToProcess, inheritanceStatePerClass, mappings, inheritanceState);
|
||||||
InheritanceState.getSuperEntityInheritanceState(
|
|
||||||
clazzToProcess, inheritanceStatePerClass, reflectionManager
|
bindQueries( clazzToProcess, mappings );
|
||||||
);
|
bindFilterDefs( clazzToProcess, mappings );
|
||||||
PersistentClass superEntity = superEntityState != null ?
|
bindTypeDefs( clazzToProcess, mappings );
|
||||||
mappings.getClass(
|
BinderHelper.bindAnyMetaDefs( clazzToProcess, mappings );
|
||||||
superEntityState.clazz.getName()
|
|
||||||
) :
|
|
||||||
null;
|
|
||||||
if ( superEntity == null ) {
|
|
||||||
//check if superclass is not a potential persistent class
|
|
||||||
if ( inheritanceState.hasParents ) {
|
|
||||||
throw new AssertionFailure(
|
|
||||||
"Subclass has to be binded after it's mother class: "
|
|
||||||
+ superEntityState.clazz.getName()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bindQueries( annotatedClass, mappings );
|
|
||||||
bindFilterDefs( annotatedClass, mappings );
|
|
||||||
bindTypeDefs( annotatedClass, mappings );
|
|
||||||
BinderHelper.bindAnyMetaDefs( annotatedClass, mappings );
|
|
||||||
|
|
||||||
String schema = "";
|
String schema = "";
|
||||||
String table = ""; //might be no @Table annotation on the annotated class
|
String table = ""; //might be no @Table annotation on the annotated class
|
||||||
String catalog = "";
|
String catalog = "";
|
||||||
String discrimValue = null;
|
|
||||||
List<UniqueConstraintHolder> uniqueConstraints = new ArrayList<UniqueConstraintHolder>();
|
List<UniqueConstraintHolder> uniqueConstraints = new ArrayList<UniqueConstraintHolder>();
|
||||||
Ejb3DiscriminatorColumn discriminatorColumn = null;
|
if ( clazzToProcess.isAnnotationPresent( javax.persistence.Table.class ) ) {
|
||||||
Ejb3JoinColumn[] inheritanceJoinedColumns = null;
|
javax.persistence.Table tabAnn = clazzToProcess.getAnnotation( javax.persistence.Table.class );
|
||||||
|
|
||||||
if ( annotatedClass.isAnnotationPresent( javax.persistence.Table.class ) ) {
|
|
||||||
javax.persistence.Table tabAnn = annotatedClass.getAnnotation( javax.persistence.Table.class );
|
|
||||||
table = tabAnn.name();
|
table = tabAnn.name();
|
||||||
schema = tabAnn.schema();
|
schema = tabAnn.schema();
|
||||||
catalog = tabAnn.catalog();
|
catalog = tabAnn.catalog();
|
||||||
uniqueConstraints = TableBinder.buildUniqueConstraintHolders( tabAnn.uniqueConstraints() );
|
uniqueConstraints = TableBinder.buildUniqueConstraintHolders( tabAnn.uniqueConstraints() );
|
||||||
}
|
}
|
||||||
final boolean hasJoinedColumns = inheritanceState.hasParents
|
|
||||||
&& InheritanceType.JOINED.equals( inheritanceState.type );
|
|
||||||
if ( hasJoinedColumns ) {
|
|
||||||
//@Inheritance(JOINED) subclass need to link back to the super entity
|
|
||||||
PrimaryKeyJoinColumns jcsAnn = annotatedClass.getAnnotation( PrimaryKeyJoinColumns.class );
|
|
||||||
boolean explicitInheritanceJoinedColumns = jcsAnn != null && jcsAnn.value().length != 0;
|
|
||||||
if ( explicitInheritanceJoinedColumns ) {
|
|
||||||
int nbrOfInhJoinedColumns = jcsAnn.value().length;
|
|
||||||
PrimaryKeyJoinColumn jcAnn;
|
|
||||||
inheritanceJoinedColumns = new Ejb3JoinColumn[nbrOfInhJoinedColumns];
|
|
||||||
for (int colIndex = 0; colIndex < nbrOfInhJoinedColumns; colIndex++) {
|
|
||||||
jcAnn = jcsAnn.value()[colIndex];
|
|
||||||
inheritanceJoinedColumns[colIndex] = Ejb3JoinColumn.buildJoinColumn(
|
|
||||||
jcAnn, null, superEntity.getIdentifier(),
|
|
||||||
(Map<String, Join>) null, (PropertyHolder) null, mappings
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
PrimaryKeyJoinColumn jcAnn = annotatedClass.getAnnotation( PrimaryKeyJoinColumn.class );
|
|
||||||
inheritanceJoinedColumns = new Ejb3JoinColumn[1];
|
|
||||||
inheritanceJoinedColumns[0] = Ejb3JoinColumn.buildJoinColumn(
|
|
||||||
jcAnn, null, superEntity.getIdentifier(),
|
|
||||||
(Map<String, Join>) null, (PropertyHolder) null, mappings
|
|
||||||
);
|
|
||||||
}
|
|
||||||
log.debug( "Subclass joined column(s) created" );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if ( annotatedClass.isAnnotationPresent( javax.persistence.PrimaryKeyJoinColumns.class )
|
|
||||||
|| annotatedClass.isAnnotationPresent( javax.persistence.PrimaryKeyJoinColumn.class ) ) {
|
|
||||||
log.warn( "Root entity should not hold an PrimaryKeyJoinColum(s), will be ignored" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.type ) ) {
|
Ejb3JoinColumn[] inheritanceJoinedColumns = makeInheritanceJoinColumns( clazzToProcess, mappings, inheritanceState, superEntity );
|
||||||
javax.persistence.DiscriminatorColumn discAnn = annotatedClass.getAnnotation(
|
Ejb3DiscriminatorColumn discriminatorColumn = null;
|
||||||
|
String discrimValue = null;
|
||||||
|
if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
|
||||||
|
javax.persistence.DiscriminatorColumn discAnn = clazzToProcess.getAnnotation(
|
||||||
javax.persistence.DiscriminatorColumn.class
|
javax.persistence.DiscriminatorColumn.class
|
||||||
);
|
);
|
||||||
DiscriminatorType discriminatorType = discAnn != null ?
|
DiscriminatorType discriminatorType = discAnn != null ?
|
||||||
discAnn.discriminatorType() :
|
discAnn.discriminatorType() :
|
||||||
DiscriminatorType.STRING;
|
DiscriminatorType.STRING;
|
||||||
|
|
||||||
org.hibernate.annotations.DiscriminatorFormula discFormulaAnn = annotatedClass.getAnnotation(
|
org.hibernate.annotations.DiscriminatorFormula discFormulaAnn = clazzToProcess.getAnnotation(
|
||||||
org.hibernate.annotations.DiscriminatorFormula.class
|
org.hibernate.annotations.DiscriminatorFormula.class
|
||||||
);
|
);
|
||||||
if ( !inheritanceState.hasParents ) {
|
if ( !inheritanceState.hasParents() ) {
|
||||||
discriminatorColumn = Ejb3DiscriminatorColumn.buildDiscriminatorColumn(
|
discriminatorColumn = Ejb3DiscriminatorColumn.buildDiscriminatorColumn(
|
||||||
discriminatorType, discAnn, discFormulaAnn, mappings
|
discriminatorType, discAnn, discFormulaAnn, mappings
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ( discAnn != null && inheritanceState.hasParents ) {
|
if ( discAnn != null && inheritanceState.hasParents() ) {
|
||||||
log.warn(
|
log.warn(
|
||||||
"Discriminator column has to be defined in the root entity, it will be ignored in subclass: {}",
|
"Discriminator column has to be defined in the root entity, it will be ignored in subclass: {}",
|
||||||
clazzToProcess.getName()
|
clazzToProcess.getName()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
discrimValue = annotatedClass.isAnnotationPresent( DiscriminatorValue.class ) ?
|
|
||||||
annotatedClass.getAnnotation( DiscriminatorValue.class ).value() :
|
discrimValue = clazzToProcess.isAnnotationPresent( DiscriminatorValue.class ) ?
|
||||||
|
clazzToProcess.getAnnotation( DiscriminatorValue.class ).value() :
|
||||||
null;
|
null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//we now know what kind of persistent entity it is
|
PersistentClass persistentClass = makePersistentClass( inheritanceState, superEntity );
|
||||||
PersistentClass persistentClass;
|
|
||||||
//create persistent class
|
Proxy proxyAnn = clazzToProcess.getAnnotation( Proxy.class );
|
||||||
if ( !inheritanceState.hasParents ) {
|
BatchSize sizeAnn = clazzToProcess.getAnnotation( BatchSize.class );
|
||||||
persistentClass = new RootClass();
|
Where whereAnn = clazzToProcess.getAnnotation( Where.class );
|
||||||
}
|
Entity entityAnn = clazzToProcess.getAnnotation( Entity.class );
|
||||||
else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.type ) ) {
|
org.hibernate.annotations.Entity hibEntityAnn = clazzToProcess.getAnnotation(
|
||||||
persistentClass = new SingleTableSubclass( superEntity );
|
|
||||||
}
|
|
||||||
else if ( InheritanceType.JOINED.equals( inheritanceState.type ) ) {
|
|
||||||
persistentClass = new JoinedSubclass( superEntity );
|
|
||||||
}
|
|
||||||
else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.type ) ) {
|
|
||||||
persistentClass = new UnionSubclass( superEntity );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new AssertionFailure( "Unknown inheritance type: " + inheritanceState.type );
|
|
||||||
}
|
|
||||||
Proxy proxyAnn = annotatedClass.getAnnotation( Proxy.class );
|
|
||||||
BatchSize sizeAnn = annotatedClass.getAnnotation( BatchSize.class );
|
|
||||||
Where whereAnn = annotatedClass.getAnnotation( Where.class );
|
|
||||||
Entity entityAnn = annotatedClass.getAnnotation( Entity.class );
|
|
||||||
org.hibernate.annotations.Entity hibEntityAnn = annotatedClass.getAnnotation(
|
|
||||||
org.hibernate.annotations.Entity.class
|
org.hibernate.annotations.Entity.class
|
||||||
);
|
);
|
||||||
org.hibernate.annotations.Cache cacheAnn = annotatedClass.getAnnotation(
|
org.hibernate.annotations.Cache cacheAnn = clazzToProcess.getAnnotation(
|
||||||
org.hibernate.annotations.Cache.class
|
org.hibernate.annotations.Cache.class
|
||||||
);
|
);
|
||||||
EntityBinder entityBinder = new EntityBinder(
|
EntityBinder entityBinder = new EntityBinder(
|
||||||
|
@ -598,14 +518,14 @@ public final class AnnotationBinder {
|
||||||
entityBinder.setInheritanceState( inheritanceState );
|
entityBinder.setInheritanceState( inheritanceState );
|
||||||
|
|
||||||
//Filters are not allowed on subclasses
|
//Filters are not allowed on subclasses
|
||||||
if ( !inheritanceState.hasParents ) {
|
if ( !inheritanceState.hasParents() ) {
|
||||||
bindFilters(clazzToProcess, entityBinder, mappings);
|
bindFilters(clazzToProcess, entityBinder, mappings);
|
||||||
}
|
}
|
||||||
|
|
||||||
entityBinder.bindEntity();
|
entityBinder.bindEntity();
|
||||||
|
|
||||||
if ( inheritanceState.hasTable() ) {
|
if ( inheritanceState.hasTable() ) {
|
||||||
Check checkAnn = annotatedClass.getAnnotation( Check.class );
|
Check checkAnn = clazzToProcess.getAnnotation( Check.class );
|
||||||
String constraints = checkAnn == null ?
|
String constraints = checkAnn == null ?
|
||||||
null :
|
null :
|
||||||
checkAnn.constraints();
|
checkAnn.constraints();
|
||||||
|
@ -617,32 +537,29 @@ public final class AnnotationBinder {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( annotatedClass.isAnnotationPresent( Table.class ) ) {
|
if ( clazzToProcess.isAnnotationPresent( Table.class ) ) {
|
||||||
log.warn( "Illegal use of @Table in a subclass of a SINGLE_TABLE hierarchy: " + clazzToProcess
|
log.warn( "Illegal use of @Table in a subclass of a SINGLE_TABLE hierarchy: " + clazzToProcess
|
||||||
.getName() );
|
.getName() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Map<String, Column[]> columnOverride = PropertyHolderBuilder.buildHierarchyColumnOverride(
|
|
||||||
// clazzToProcess,
|
|
||||||
// persistentClass.getClassName()
|
|
||||||
// );
|
|
||||||
PropertyHolder propertyHolder = PropertyHolderBuilder.buildPropertyHolder(
|
PropertyHolder propertyHolder = PropertyHolderBuilder.buildPropertyHolder(
|
||||||
clazzToProcess,
|
clazzToProcess,
|
||||||
persistentClass,
|
persistentClass,
|
||||||
entityBinder, mappings, inheritanceStatePerClass
|
entityBinder, mappings, inheritanceStatePerClass
|
||||||
);
|
);
|
||||||
|
|
||||||
javax.persistence.SecondaryTable secTabAnn = annotatedClass.getAnnotation(
|
javax.persistence.SecondaryTable secTabAnn = clazzToProcess.getAnnotation(
|
||||||
javax.persistence.SecondaryTable.class
|
javax.persistence.SecondaryTable.class
|
||||||
);
|
);
|
||||||
javax.persistence.SecondaryTables secTabsAnn = annotatedClass.getAnnotation(
|
javax.persistence.SecondaryTables secTabsAnn = clazzToProcess.getAnnotation(
|
||||||
javax.persistence.SecondaryTables.class
|
javax.persistence.SecondaryTables.class
|
||||||
);
|
);
|
||||||
entityBinder.firstLevelSecondaryTablesBinding( secTabAnn, secTabsAnn );
|
entityBinder.firstLevelSecondaryTablesBinding( secTabAnn, secTabsAnn );
|
||||||
|
|
||||||
OnDelete onDeleteAnn = annotatedClass.getAnnotation( OnDelete.class );
|
OnDelete onDeleteAnn = clazzToProcess.getAnnotation( OnDelete.class );
|
||||||
boolean onDeleteAppropriate = false;
|
boolean onDeleteAppropriate = false;
|
||||||
if ( InheritanceType.JOINED.equals( inheritanceState.type ) && inheritanceState.hasParents ) {
|
if ( InheritanceType.JOINED.equals( inheritanceState.getType() ) && inheritanceState.hasParents() ) {
|
||||||
onDeleteAppropriate = true;
|
onDeleteAppropriate = true;
|
||||||
final JoinedSubclass jsc = (JoinedSubclass) persistentClass;
|
final JoinedSubclass jsc = (JoinedSubclass) persistentClass;
|
||||||
if ( persistentClass.getEntityPersisterClass() == null ) {
|
if ( persistentClass.getEntityPersisterClass() == null ) {
|
||||||
|
@ -650,7 +567,7 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
SimpleValue key = new DependantValue( jsc.getTable(), jsc.getIdentifier() );
|
SimpleValue key = new DependantValue( jsc.getTable(), jsc.getIdentifier() );
|
||||||
jsc.setKey( key );
|
jsc.setKey( key );
|
||||||
ForeignKey fk = annotatedClass.getAnnotation( ForeignKey.class );
|
ForeignKey fk = clazzToProcess.getAnnotation( ForeignKey.class );
|
||||||
if ( fk != null && !BinderHelper.isDefault( fk.name() ) ) {
|
if ( fk != null && !BinderHelper.isDefault( fk.name() ) ) {
|
||||||
key.setForeignKeyName( fk.name() );
|
key.setForeignKeyName( fk.name() );
|
||||||
}
|
}
|
||||||
|
@ -666,14 +583,14 @@ public final class AnnotationBinder {
|
||||||
mappings.addSecondPass( new CreateKeySecondPass( jsc ) );
|
mappings.addSecondPass( new CreateKeySecondPass( jsc ) );
|
||||||
|
|
||||||
}
|
}
|
||||||
else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.type ) ) {
|
else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
|
||||||
if ( inheritanceState.hasParents ) {
|
if ( inheritanceState.hasParents() ) {
|
||||||
if ( persistentClass.getEntityPersisterClass() == null ) {
|
if ( persistentClass.getEntityPersisterClass() == null ) {
|
||||||
persistentClass.getRootClass().setEntityPersisterClass( SingleTableEntityPersister.class );
|
persistentClass.getRootClass().setEntityPersisterClass( SingleTableEntityPersister.class );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( inheritanceState.hasSons || !discriminatorColumn.isImplicit() ) {
|
if ( inheritanceState.hasSiblings() || !discriminatorColumn.isImplicit() ) {
|
||||||
//need a discriminator column
|
//need a discriminator column
|
||||||
bindDiscriminatorToPersistentClass(
|
bindDiscriminatorToPersistentClass(
|
||||||
(RootClass) persistentClass,
|
(RootClass) persistentClass,
|
||||||
|
@ -685,8 +602,8 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.type ) ) {
|
else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.getType() ) ) {
|
||||||
if ( inheritanceState.hasParents ) {
|
if ( inheritanceState.hasParents() ) {
|
||||||
if ( persistentClass.getEntityPersisterClass() == null ) {
|
if ( persistentClass.getEntityPersisterClass() == null ) {
|
||||||
persistentClass.getRootClass().setEntityPersisterClass( UnionSubclassEntityPersister.class );
|
persistentClass.getRootClass().setEntityPersisterClass( UnionSubclassEntityPersister.class );
|
||||||
}
|
}
|
||||||
|
@ -699,7 +616,7 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
//try to find class level generators
|
//try to find class level generators
|
||||||
HashMap<String, IdGenerator> classGenerators = buildLocalGenerators( annotatedClass, mappings );
|
HashMap<String, IdGenerator> classGenerators = buildLocalGenerators( clazzToProcess, mappings );
|
||||||
|
|
||||||
// check properties
|
// check properties
|
||||||
List<PropertyData> elements =
|
List<PropertyData> elements =
|
||||||
|
@ -709,30 +626,29 @@ public final class AnnotationBinder {
|
||||||
if ( elements == null ) {
|
if ( elements == null ) {
|
||||||
throw new AnnotationException( "No identifier specified for entity: " + propertyHolder.getEntityName() );
|
throw new AnnotationException( "No identifier specified for entity: " + propertyHolder.getEntityName() );
|
||||||
}
|
}
|
||||||
final boolean subclassAndSingleTableStrategy = inheritanceState.type == InheritanceType.SINGLE_TABLE
|
final boolean subclassAndSingleTableStrategy = inheritanceState.getType() == InheritanceType.SINGLE_TABLE
|
||||||
&& inheritanceState.hasParents;
|
&& inheritanceState.hasParents();
|
||||||
//process idclass if any
|
//process idclass if any
|
||||||
Set<String> idProperties = new HashSet<String>();
|
Set<String> idProperties = new HashSet<String>();
|
||||||
IdClass idClass = null;
|
IdClass idClass = null;
|
||||||
XClass current = null;
|
XClass current = null;
|
||||||
if ( !inheritanceState.hasParents ) {
|
if ( !inheritanceState.hasParents() ) {
|
||||||
//look for idClass
|
//look for idClass
|
||||||
current = inheritanceState.clazz;
|
|
||||||
InheritanceState state = inheritanceState;
|
InheritanceState state = inheritanceState;
|
||||||
do {
|
do {
|
||||||
current = state.clazz;
|
current = state.getClazz();
|
||||||
if ( current.isAnnotationPresent( IdClass.class ) ) {
|
if ( current.isAnnotationPresent( IdClass.class ) ) {
|
||||||
idClass = current.getAnnotation( IdClass.class );
|
idClass = current.getAnnotation( IdClass.class );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
state = InheritanceState.getSuperclassInheritanceState(
|
state = InheritanceState.getSuperclassInheritanceState(
|
||||||
current, inheritanceStatePerClass, reflectionManager
|
current, inheritanceStatePerClass, mappings.getReflectionManager()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
while ( state != null );
|
while ( state != null );
|
||||||
}
|
}
|
||||||
if ( idClass != null ) {
|
if ( idClass != null ) {
|
||||||
XClass compositeClass = reflectionManager.toXClass( idClass.value() );
|
XClass compositeClass = mappings.getReflectionManager().toXClass( idClass.value() );
|
||||||
boolean isComponent = true;
|
boolean isComponent = true;
|
||||||
boolean propertyAnnotated = entityBinder.isPropertyAnnotated( compositeClass );
|
boolean propertyAnnotated = entityBinder.isPropertyAnnotated( compositeClass );
|
||||||
String propertyAccessor = entityBinder.getPropertyAccessor( compositeClass );
|
String propertyAccessor = entityBinder.getPropertyAccessor( compositeClass );
|
||||||
|
@ -837,7 +753,7 @@ public final class AnnotationBinder {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !inheritanceState.hasParents ) {
|
if ( !inheritanceState.hasParents() ) {
|
||||||
final RootClass rootClass = (RootClass) persistentClass;
|
final RootClass rootClass = (RootClass) persistentClass;
|
||||||
mappings.addSecondPass( new CreateKeySecondPass( rootClass ) );
|
mappings.addSecondPass( new CreateKeySecondPass( rootClass ) );
|
||||||
}
|
}
|
||||||
|
@ -848,14 +764,121 @@ public final class AnnotationBinder {
|
||||||
mappings.addClass( persistentClass );
|
mappings.addClass( persistentClass );
|
||||||
|
|
||||||
//Process secondary tables and complementary definitions (ie o.h.a.Table)
|
//Process secondary tables and complementary definitions (ie o.h.a.Table)
|
||||||
mappings.addSecondPass( new SecondaryTableSecondPass( entityBinder, propertyHolder, annotatedClass ) );
|
mappings.addSecondPass( new SecondaryTableSecondPass( entityBinder, propertyHolder, clazzToProcess ) );
|
||||||
|
|
||||||
//add process complementary Table definition (index & all)
|
//add process complementary Table definition (index & all)
|
||||||
entityBinder.processComplementaryTableDefinitions( annotatedClass.getAnnotation( org.hibernate.annotations.Table.class ) );
|
entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Table.class ) );
|
||||||
entityBinder.processComplementaryTableDefinitions( annotatedClass.getAnnotation( org.hibernate.annotations.Tables.class ) );
|
entityBinder.processComplementaryTableDefinitions( clazzToProcess.getAnnotation( org.hibernate.annotations.Tables.class ) );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static PersistentClass makePersistentClass(InheritanceState inheritanceState, PersistentClass superEntity) {
|
||||||
|
//we now know what kind of persistent entity it is
|
||||||
|
PersistentClass persistentClass;
|
||||||
|
//create persistent class
|
||||||
|
if ( !inheritanceState.hasParents() ) {
|
||||||
|
persistentClass = new RootClass();
|
||||||
|
}
|
||||||
|
else if ( InheritanceType.SINGLE_TABLE.equals( inheritanceState.getType() ) ) {
|
||||||
|
persistentClass = new SingleTableSubclass( superEntity );
|
||||||
|
}
|
||||||
|
else if ( InheritanceType.JOINED.equals( inheritanceState.getType() ) ) {
|
||||||
|
persistentClass = new JoinedSubclass( superEntity );
|
||||||
|
}
|
||||||
|
else if ( InheritanceType.TABLE_PER_CLASS.equals( inheritanceState.getType() ) ) {
|
||||||
|
persistentClass = new UnionSubclass( superEntity );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new AssertionFailure( "Unknown inheritance type: " + inheritanceState.getType() );
|
||||||
|
}
|
||||||
|
return persistentClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Ejb3JoinColumn[] makeInheritanceJoinColumns(XClass clazzToProcess, ExtendedMappings mappings, InheritanceState inheritanceState, PersistentClass superEntity) {
|
||||||
|
Ejb3JoinColumn[] inheritanceJoinedColumns = null;
|
||||||
|
final boolean hasJoinedColumns = inheritanceState.hasParents()
|
||||||
|
&& InheritanceType.JOINED.equals( inheritanceState.getType() );
|
||||||
|
if ( hasJoinedColumns ) {
|
||||||
|
//@Inheritance(JOINED) subclass need to link back to the super entity
|
||||||
|
PrimaryKeyJoinColumns jcsAnn = clazzToProcess.getAnnotation( PrimaryKeyJoinColumns.class );
|
||||||
|
boolean explicitInheritanceJoinedColumns = jcsAnn != null && jcsAnn.value().length != 0;
|
||||||
|
if ( explicitInheritanceJoinedColumns ) {
|
||||||
|
int nbrOfInhJoinedColumns = jcsAnn.value().length;
|
||||||
|
PrimaryKeyJoinColumn jcAnn;
|
||||||
|
inheritanceJoinedColumns = new Ejb3JoinColumn[nbrOfInhJoinedColumns];
|
||||||
|
for (int colIndex = 0; colIndex < nbrOfInhJoinedColumns; colIndex++) {
|
||||||
|
jcAnn = jcsAnn.value()[colIndex];
|
||||||
|
inheritanceJoinedColumns[colIndex] = Ejb3JoinColumn.buildJoinColumn(
|
||||||
|
jcAnn, null, superEntity.getIdentifier(),
|
||||||
|
( Map<String, Join> ) null, ( PropertyHolder ) null, mappings
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PrimaryKeyJoinColumn jcAnn = clazzToProcess.getAnnotation( PrimaryKeyJoinColumn.class );
|
||||||
|
inheritanceJoinedColumns = new Ejb3JoinColumn[1];
|
||||||
|
inheritanceJoinedColumns[0] = Ejb3JoinColumn.buildJoinColumn(
|
||||||
|
jcAnn, null, superEntity.getIdentifier(),
|
||||||
|
(Map<String, Join>) null, (PropertyHolder) null, mappings
|
||||||
|
);
|
||||||
|
}
|
||||||
|
log.debug( "Subclass joined column(s) created" );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ( clazzToProcess.isAnnotationPresent( PrimaryKeyJoinColumns.class )
|
||||||
|
|| clazzToProcess.isAnnotationPresent( PrimaryKeyJoinColumn.class ) ) {
|
||||||
|
log.warn( "Root entity should not hold an PrimaryKeyJoinColum(s), will be ignored" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return inheritanceJoinedColumns;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PersistentClass getSuperEntity(XClass clazzToProcess, Map<XClass, InheritanceState> inheritanceStatePerClass, ExtendedMappings mappings, InheritanceState inheritanceState) {
|
||||||
|
final ReflectionManager reflectionManager = mappings.getReflectionManager();
|
||||||
|
InheritanceState superEntityState =
|
||||||
|
InheritanceState.getInheritanceStateOfSuperEntity(
|
||||||
|
clazzToProcess, inheritanceStatePerClass, reflectionManager
|
||||||
|
);
|
||||||
|
PersistentClass superEntity = superEntityState != null ?
|
||||||
|
mappings.getClass(
|
||||||
|
superEntityState.getClazz().getName()
|
||||||
|
) :
|
||||||
|
null;
|
||||||
|
if ( superEntity == null ) {
|
||||||
|
//check if superclass is not a potential persistent class
|
||||||
|
if ( inheritanceState.hasParents() ) {
|
||||||
|
throw new AssertionFailure(
|
||||||
|
"Subclass has to be binded after it's mother class: "
|
||||||
|
+ superEntityState.getClazz().getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return superEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean isEntityClassType(XClass clazzToProcess, AnnotatedClassType classType) {
|
||||||
|
if ( AnnotatedClassType.EMBEDDABLE_SUPERCLASS.equals( classType ) //will be processed by their subentities
|
||||||
|
|| AnnotatedClassType.NONE.equals( classType ) //to be ignored
|
||||||
|
|| AnnotatedClassType.EMBEDDABLE.equals( classType ) //allow embeddable element declaration
|
||||||
|
) {
|
||||||
|
if ( AnnotatedClassType.NONE.equals( classType )
|
||||||
|
&& clazzToProcess.isAnnotationPresent( org.hibernate.annotations.Entity.class ) ) {
|
||||||
|
log.warn( "Class annotated @org.hibernate.annotations.Entity but not javax.persistence.Entity "
|
||||||
|
+ "(most likely a user error): {}", clazzToProcess.getName() );
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !classType.equals( AnnotatedClassType.ENTITY ) ) {
|
||||||
|
throw new AnnotationException(
|
||||||
|
"Annotated class should have a @javax.persistence.Entity, @javax.persistence.Embeddable or @javax.persistence.EmbeddedSuperclass annotation: " + clazzToProcess
|
||||||
|
.getName()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the annotated elements
|
* Get the annotated elements
|
||||||
* Guess the annotated element from @Id or @EmbeddedId presence
|
* Guess the annotated element from @Id or @EmbeddedId presence
|
||||||
|
@ -874,19 +897,19 @@ public final class AnnotationBinder {
|
||||||
int deep = classesToProcess.size();
|
int deep = classesToProcess.size();
|
||||||
boolean hasIdentifier = false;
|
boolean hasIdentifier = false;
|
||||||
|
|
||||||
assert !inheritanceState.isEmbeddableSuperclass;
|
assert !inheritanceState.isEmbeddableSuperclass();
|
||||||
Boolean isExplicitPropertyAnnotated = null;
|
Boolean isExplicitPropertyAnnotated = null;
|
||||||
String explicitAccessType;
|
String explicitAccessType;
|
||||||
if ( inheritanceState.hasParents ) {
|
if ( inheritanceState.hasParents() ) {
|
||||||
InheritanceState superEntityState =
|
InheritanceState superEntityState =
|
||||||
InheritanceState.getSuperEntityInheritanceState(
|
InheritanceState.getInheritanceStateOfSuperEntity(
|
||||||
clazzToProcess, inheritanceStatePerClass, mappings.getReflectionManager()
|
clazzToProcess, inheritanceStatePerClass, mappings.getReflectionManager()
|
||||||
);
|
);
|
||||||
isExplicitPropertyAnnotated = superEntityState != null ?
|
isExplicitPropertyAnnotated = superEntityState != null ?
|
||||||
superEntityState.isPropertyAnnotated :
|
superEntityState.isPropertyAnnotated() :
|
||||||
null;
|
null;
|
||||||
explicitAccessType = superEntityState != null ?
|
explicitAccessType = superEntityState != null ?
|
||||||
superEntityState.accessType :
|
superEntityState.getAccessType() :
|
||||||
null;
|
null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -928,7 +951,7 @@ public final class AnnotationBinder {
|
||||||
exceptionWhileWalkingElements = e;
|
exceptionWhileWalkingElements = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !hasIdentifier && !inheritanceState.hasParents ) {
|
if ( !hasIdentifier && !inheritanceState.hasParents() ) {
|
||||||
if ( isExplicitPropertyAnnotated != null ) {
|
if ( isExplicitPropertyAnnotated != null ) {
|
||||||
//the original exception is legitimate
|
//the original exception is legitimate
|
||||||
if ( exceptionWhileWalkingElements != null) throw exceptionWhileWalkingElements;
|
if ( exceptionWhileWalkingElements != null) throw exceptionWhileWalkingElements;
|
||||||
|
@ -953,9 +976,9 @@ public final class AnnotationBinder {
|
||||||
//TODO set the access type here?
|
//TODO set the access type here?
|
||||||
entityBinder.setPropertyAnnotated( isPropertyAnnotated );
|
entityBinder.setPropertyAnnotated( isPropertyAnnotated );
|
||||||
entityBinder.setPropertyAccessor( accessType );
|
entityBinder.setPropertyAccessor( accessType );
|
||||||
inheritanceState.isPropertyAnnotated = isPropertyAnnotated;
|
inheritanceState.setPropertyAnnotated( isPropertyAnnotated );
|
||||||
inheritanceState.accessType = accessType;
|
inheritanceState.setAccessType( accessType );
|
||||||
return hasIdentifier || inheritanceState.hasParents ?
|
return hasIdentifier || inheritanceState.hasParents() ?
|
||||||
elements :
|
elements :
|
||||||
null;
|
null;
|
||||||
}
|
}
|
||||||
|
@ -983,16 +1006,16 @@ public final class AnnotationBinder {
|
||||||
|
|
||||||
currentClassInHierarchy = superClass;
|
currentClassInHierarchy = superClass;
|
||||||
}
|
}
|
||||||
while ( superclassState != null && superclassState.isEmbeddableSuperclass );
|
while ( superclassState != null && superclassState.isEmbeddableSuperclass() );
|
||||||
|
|
||||||
//add @MappedSuperclass in the metadata
|
//add @MappedSuperclass in the metadata
|
||||||
// classes from 0 to n-1 are @MappedSuperclass and should be linked
|
// classes from 0 to n-1 are @MappedSuperclass and should be linked
|
||||||
org.hibernate.mapping.MappedSuperclass mappedSuperclass = null;
|
org.hibernate.mapping.MappedSuperclass mappedSuperclass = null;
|
||||||
final InheritanceState superEntityState =
|
final InheritanceState superEntityState =
|
||||||
InheritanceState.getSuperEntityInheritanceState(annotatedClass, inheritanceStatePerClass, reflectionManager);
|
InheritanceState.getInheritanceStateOfSuperEntity(annotatedClass, inheritanceStatePerClass, reflectionManager);
|
||||||
PersistentClass superEntity =
|
PersistentClass superEntity =
|
||||||
superEntityState != null ?
|
superEntityState != null ?
|
||||||
mappings.getClass( superEntityState.clazz.getName() ) :
|
mappings.getClass( superEntityState.getClazz().getName() ) :
|
||||||
null;
|
null;
|
||||||
final int lastMappedSuperclass = classesToProcess.size() - 1;
|
final int lastMappedSuperclass = classesToProcess.size() - 1;
|
||||||
for ( int index = 0 ; index < lastMappedSuperclass ; index++ ) {
|
for ( int index = 0 ; index < lastMappedSuperclass ; index++ ) {
|
||||||
|
@ -1139,7 +1162,7 @@ public final class AnnotationBinder {
|
||||||
String localPropertyAccessor = access != null ?
|
String localPropertyAccessor = access != null ?
|
||||||
access.value() :
|
access.value() :
|
||||||
null;
|
null;
|
||||||
String accessType = null;
|
String accessType;
|
||||||
if ( "property".equals( localPropertyAccessor ) || "field".equals( localPropertyAccessor ) ) {
|
if ( "property".equals( localPropertyAccessor ) || "field".equals( localPropertyAccessor ) ) {
|
||||||
accessType = localPropertyAccessor;
|
accessType = localPropertyAccessor;
|
||||||
}
|
}
|
||||||
|
@ -1579,8 +1602,6 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
Cascade hibernateCascade = property.getAnnotation( Cascade.class );
|
Cascade hibernateCascade = property.getAnnotation( Cascade.class );
|
||||||
NotFound notFound = property.getAnnotation( NotFound.class );
|
|
||||||
boolean ignoreNotFound = notFound != null && notFound.action().equals( NotFoundAction.IGNORE );
|
|
||||||
OnDelete onDeleteAnn = property.getAnnotation( OnDelete.class );
|
OnDelete onDeleteAnn = property.getAnnotation( OnDelete.class );
|
||||||
boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE.equals( onDeleteAnn.action() );
|
boolean onDeleteCascade = onDeleteAnn != null && OnDeleteAction.CASCADE.equals( onDeleteAnn.action() );
|
||||||
JoinTable assocTable = property.getAnnotation( JoinTable.class );
|
JoinTable assocTable = property.getAnnotation( JoinTable.class );
|
||||||
|
@ -1654,7 +1675,7 @@ public final class AnnotationBinder {
|
||||||
collectionBinder.setMappings( mappings );
|
collectionBinder.setMappings( mappings );
|
||||||
collectionBinder.setPropertyAccessorName( inferredData.getDefaultAccess() );
|
collectionBinder.setPropertyAccessorName( inferredData.getDefaultAccess() );
|
||||||
|
|
||||||
Ejb3Column[] elementColumns = null;
|
Ejb3Column[] elementColumns;
|
||||||
PropertyData virtualProperty = new WrappedInferredData( inferredData, "element" );
|
PropertyData virtualProperty = new WrappedInferredData( inferredData, "element" );
|
||||||
if ( property.isAnnotationPresent( Column.class ) || property.isAnnotationPresent(
|
if ( property.isAnnotationPresent( Column.class ) || property.isAnnotationPresent(
|
||||||
Formula.class
|
Formula.class
|
||||||
|
@ -1860,7 +1881,7 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//define whether the type is a component or not
|
//define whether the type is a component or not
|
||||||
boolean isComponent = false;
|
boolean isComponent;
|
||||||
Embeddable embeddableAnn = returnedClass.getAnnotation( Embeddable.class );
|
Embeddable embeddableAnn = returnedClass.getAnnotation( Embeddable.class );
|
||||||
Embedded embeddedAnn = property.getAnnotation( Embedded.class );
|
Embedded embeddedAnn = property.getAnnotation( Embedded.class );
|
||||||
isComponent = embeddedAnn != null || embeddableAnn != null;
|
isComponent = embeddedAnn != null || embeddableAnn != null;
|
||||||
|
@ -2185,9 +2206,7 @@ public final class AnnotationBinder {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
RootClass rootClass = (RootClass) persistentClass;
|
RootClass rootClass = (RootClass) persistentClass;
|
||||||
String persistentClassName = rootClass == null ?
|
String persistentClassName = rootClass.getClassName();
|
||||||
null :
|
|
||||||
rootClass.getClassName();
|
|
||||||
SimpleValue id;
|
SimpleValue id;
|
||||||
if ( isComposite ) {
|
if ( isComposite ) {
|
||||||
id = fillComponent(
|
id = fillComponent(
|
||||||
|
@ -2620,6 +2639,14 @@ public final class AnnotationBinder {
|
||||||
return mappings.getReflectionManager().equals( clazz, void.class );
|
return mappings.getReflectionManager().equals( clazz, void.class );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For the mapped entities build some temporary data-structure containing information about the
|
||||||
|
* inheritance status of a class.
|
||||||
|
*
|
||||||
|
* @param orderedClasses Order list of all annotated entities and their mapped superclasses
|
||||||
|
* @param reflectionManager Reference to the reflection manager (commons-annotations)
|
||||||
|
* @return A map of {@code InheritanceState}s keyed against their {@code XClass}.
|
||||||
|
*/
|
||||||
public static Map<XClass, InheritanceState> buildInheritanceStates(
|
public static Map<XClass, InheritanceState> buildInheritanceStates(
|
||||||
List<XClass> orderedClasses, ReflectionManager reflectionManager
|
List<XClass> orderedClasses, ReflectionManager reflectionManager
|
||||||
) {
|
) {
|
||||||
|
@ -2635,22 +2662,22 @@ public final class AnnotationBinder {
|
||||||
if ( superclassState != null ) {
|
if ( superclassState != null ) {
|
||||||
//the classes are ordered thus preventing an NPE
|
//the classes are ordered thus preventing an NPE
|
||||||
//FIXME if an entity has subclasses annotated @MappedSperclass wo sub @Entity this is wrong
|
//FIXME if an entity has subclasses annotated @MappedSperclass wo sub @Entity this is wrong
|
||||||
superclassState.hasSons = true;
|
superclassState.setHasSiblings( true );
|
||||||
InheritanceState superEntityState = InheritanceState.getSuperEntityInheritanceState(
|
InheritanceState superEntityState = InheritanceState.getInheritanceStateOfSuperEntity(
|
||||||
clazz, inheritanceStatePerClass,
|
clazz, inheritanceStatePerClass,
|
||||||
reflectionManager
|
reflectionManager
|
||||||
);
|
);
|
||||||
state.hasParents = superEntityState != null;
|
state.setHasParents( superEntityState != null );
|
||||||
final boolean nonDefault = state.type != null && !InheritanceType.SINGLE_TABLE.equals( state.type );
|
final boolean nonDefault = state.getType() != null && !InheritanceType.SINGLE_TABLE.equals( state.getType() );
|
||||||
if ( superclassState.type != null ) {
|
if ( superclassState.getType() != null ) {
|
||||||
final boolean mixingStrategy = state.type != null && !state.type.equals( superclassState.type );
|
final boolean mixingStrategy = state.getType() != null && !state.getType().equals( superclassState.getType() );
|
||||||
if ( nonDefault && mixingStrategy ) {
|
if ( nonDefault && mixingStrategy ) {
|
||||||
log.warn(
|
log.warn(
|
||||||
"Mixing inheritance strategy in a entity hierarchy is not allowed, ignoring sub strategy in: {}",
|
"Mixing inheritance strategy in a entity hierarchy is not allowed, ignoring sub strategy in: {}",
|
||||||
clazz.getName()
|
clazz.getName()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
state.type = superclassState.type;
|
state.setType( superclassState.getType() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inheritanceStatePerClass.put( clazz, state );
|
inheritanceStatePerClass.put( clazz, state );
|
||||||
|
|
|
@ -123,7 +123,6 @@ public class AnnotationConfiguration extends Configuration {
|
||||||
private Set<String> defaultNamedGenerators;
|
private Set<String> defaultNamedGenerators;
|
||||||
private Map<String, Properties> generatorTables;
|
private Map<String, Properties> generatorTables;
|
||||||
private Map<Table, List<UniqueConstraintHolder>> uniqueConstraintHoldersByTable;
|
private Map<Table, List<UniqueConstraintHolder>> uniqueConstraintHoldersByTable;
|
||||||
// private Map<Table, List<String[]>> tableUniqueConstraints;
|
|
||||||
private Map<String, String> mappedByResolver;
|
private Map<String, String> mappedByResolver;
|
||||||
private Map<String, String> propertyRefResolver;
|
private Map<String, String> propertyRefResolver;
|
||||||
private Map<String, AnyMetaDef> anyMetaDefs;
|
private Map<String, AnyMetaDef> anyMetaDefs;
|
||||||
|
@ -146,10 +145,30 @@ public class AnnotationConfiguration extends Configuration {
|
||||||
super( sf );
|
super( sf );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes the list of entities annotated with {@code @Entity} or {@code @MappedSuperclass} and returns them in an
|
||||||
|
* ordered list.
|
||||||
|
*
|
||||||
|
* @param original The list of all entities annotated with {@code @Entity} or {@code @MappedSuperclass}
|
||||||
|
* @return Ordered list of entities including superclasses for entities which have any. Class hierachies are
|
||||||
|
* listed bottom up (starting from the top level base class). There is no indication in the list when a new class
|
||||||
|
* (hierarchy) starts.
|
||||||
|
*/
|
||||||
protected List<XClass> orderAndFillHierarchy(List<XClass> original) {
|
protected List<XClass> orderAndFillHierarchy(List<XClass> original) {
|
||||||
//TODO remove embeddable
|
|
||||||
List<XClass> copy = new ArrayList<XClass>( original );
|
List<XClass> copy = new ArrayList<XClass>( original );
|
||||||
//for each class, copy all the relevant hierarchy
|
insertMappedSuperclasses( original, copy );
|
||||||
|
|
||||||
|
// order the hierarchy
|
||||||
|
List<XClass> workingCopy = new ArrayList<XClass>( copy );
|
||||||
|
List<XClass> newList = new ArrayList<XClass>( copy.size() );
|
||||||
|
while ( workingCopy.size() > 0 ) {
|
||||||
|
XClass clazz = workingCopy.get( 0 );
|
||||||
|
orderHierarchy( workingCopy, newList, copy, clazz );
|
||||||
|
}
|
||||||
|
return newList;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertMappedSuperclasses(List<XClass> original, List<XClass> copy) {
|
||||||
for ( XClass clazz : original ) {
|
for ( XClass clazz : original ) {
|
||||||
XClass superClass = clazz.getSuperclass();
|
XClass superClass = clazz.getSuperclass();
|
||||||
while ( superClass != null && !reflectionManager.equals( superClass, Object.class ) && !copy.contains(
|
while ( superClass != null && !reflectionManager.equals( superClass, Object.class ) && !copy.contains(
|
||||||
|
@ -162,13 +181,6 @@ public class AnnotationConfiguration extends Configuration {
|
||||||
superClass = superClass.getSuperclass();
|
superClass = superClass.getSuperclass();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
List<XClass> workingCopy = new ArrayList<XClass>( copy );
|
|
||||||
List<XClass> newList = new ArrayList<XClass>( copy.size() );
|
|
||||||
while ( workingCopy.size() > 0 ) {
|
|
||||||
XClass clazz = workingCopy.get( 0 );
|
|
||||||
orderHierarchy( workingCopy, newList, copy, clazz );
|
|
||||||
}
|
|
||||||
return newList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void orderHierarchy(List<XClass> copy, List<XClass> newList, List<XClass> original, XClass clazz) {
|
private void orderHierarchy(List<XClass> copy, List<XClass> newList, List<XClass> original, XClass clazz) {
|
||||||
|
@ -598,6 +610,7 @@ public class AnnotationConfiguration extends Configuration {
|
||||||
orderedClasses, reflectionManager
|
orderedClasses, reflectionManager
|
||||||
);
|
);
|
||||||
ExtendedMappings mappings = createExtendedMappings();
|
ExtendedMappings mappings = createExtendedMappings();
|
||||||
|
|
||||||
for ( XClass clazz : orderedClasses ) {
|
for ( XClass clazz : orderedClasses ) {
|
||||||
//todo use the same extended mapping
|
//todo use the same extended mapping
|
||||||
AnnotationBinder.bindClass( clazz, inheritanceStatePerClass, mappings );
|
AnnotationBinder.bindClass( clazz, inheritanceStatePerClass, mappings );
|
||||||
|
@ -1166,20 +1179,6 @@ public class AnnotationConfiguration extends Configuration {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected class ExtendedMappingsImpl extends MappingsImpl implements ExtendedMappings {
|
protected class ExtendedMappingsImpl extends MappingsImpl implements ExtendedMappings {
|
||||||
// private final Map<String, IdGenerator> namedGenerators;
|
|
||||||
// private final Map<String, Map<String, Join>> joins;
|
|
||||||
// private final Map<String, AnnotatedClassType> classTypes;
|
|
||||||
// private final Map<String, Properties> generatorTables;
|
|
||||||
// private final Map<Table, List<String[]>> tableUniqueConstraints;
|
|
||||||
// private final Map<String, String> mappedByResolver;
|
|
||||||
// private final Map<String, String> propertyRefResolver;
|
|
||||||
// private final ReflectionManager reflectionManager;
|
|
||||||
// private final Set<String> defaultNamedQueryNames;
|
|
||||||
// private final Set<String> defaultNamedNativeQueryNames;
|
|
||||||
// private final Set<String> defaultSqlResulSetMappingNames;
|
|
||||||
// private final Set<String> defaultNamedGenerators;
|
|
||||||
// private final Map<String, AnyMetaDef> anyMetaDefs;
|
|
||||||
|
|
||||||
public void addDefaultGenerator(IdGenerator generator) {
|
public void addDefaultGenerator(IdGenerator generator) {
|
||||||
this.addGenerator( generator );
|
this.addGenerator( generator );
|
||||||
defaultNamedGenerators.add( generator.getName() );
|
defaultNamedGenerators.add( generator.getName() );
|
||||||
|
|
|
@ -591,7 +591,7 @@ public class BinderHelper {
|
||||||
"Declaring class is not found in the inheritance state hierarchy: " + declaringClass
|
"Declaring class is not found in the inheritance state hierarchy: " + declaringClass
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ( inheritanceState.isEmbeddableSuperclass ) {
|
if ( inheritanceState.isEmbeddableSuperclass() ) {
|
||||||
retrieve = true;
|
retrieve = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -113,7 +113,7 @@ public class ClassPropertyHolder extends AbstractPropertyHolder {
|
||||||
"Declaring class is not found in the inheritance state hierarchy: " + declaringClass
|
"Declaring class is not found in the inheritance state hierarchy: " + declaringClass
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ( inheritanceState.isEmbeddableSuperclass ) {
|
if ( inheritanceState.isEmbeddableSuperclass() ) {
|
||||||
persistentClass.addMappedsuperclassProperty(prop);
|
persistentClass.addMappedsuperclassProperty(prop);
|
||||||
addPropertyToMappedSuperclass( prop, declaringClass );
|
addPropertyToMappedSuperclass( prop, declaringClass );
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ public class ClassPropertyHolder extends AbstractPropertyHolder {
|
||||||
"Declaring class is not found in the inheritance state hierarchy: " + declaringClass
|
"Declaring class is not found in the inheritance state hierarchy: " + declaringClass
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ( inheritanceState.isEmbeddableSuperclass ) {
|
if ( inheritanceState.isEmbeddableSuperclass() ) {
|
||||||
join.addMappedsuperclassProperty(prop);
|
join.addMappedsuperclassProperty(prop);
|
||||||
addPropertyToMappedSuperclass( prop, declaringClass );
|
addPropertyToMappedSuperclass( prop, declaringClass );
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,56 +33,58 @@ import org.hibernate.annotations.common.reflection.XAnnotatedElement;
|
||||||
import org.hibernate.annotations.common.reflection.XClass;
|
import org.hibernate.annotations.common.reflection.XClass;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Some extra data to the inheritance position of a class
|
* Some extra data to the inheritance position of a class.
|
||||||
*
|
*
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
*/
|
*/
|
||||||
public class InheritanceState {
|
public class InheritanceState {
|
||||||
public InheritanceState(XClass clazz) {
|
public InheritanceState(XClass clazz) {
|
||||||
this.clazz = clazz;
|
this.setClazz( clazz );
|
||||||
extractInheritanceType();
|
extractInheritanceType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public XClass clazz;
|
private XClass clazz;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* has son either mappedsuperclass son or entity son
|
* Has sibling (either mappedsuperclass entity)
|
||||||
*/
|
*/
|
||||||
public boolean hasSons = false;
|
private boolean hasSiblings = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* a mother entity is available
|
* a mother entity is available
|
||||||
*/
|
*/
|
||||||
public boolean hasParents = false;
|
private boolean hasParents = false;
|
||||||
public InheritanceType type;
|
private InheritanceType type;
|
||||||
public boolean isEmbeddableSuperclass = false;
|
private boolean isEmbeddableSuperclass = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* only defined on embedded superclasses
|
* only defined on embedded superclasses
|
||||||
*/
|
*/
|
||||||
public String accessType = null;
|
private String accessType = null;
|
||||||
public Boolean isPropertyAnnotated;
|
private Boolean isPropertyAnnotated;
|
||||||
|
|
||||||
private void extractInheritanceType() {
|
private void extractInheritanceType() {
|
||||||
XAnnotatedElement element = clazz;
|
XAnnotatedElement element = getClazz();
|
||||||
Inheritance inhAnn = element.getAnnotation( Inheritance.class );
|
Inheritance inhAnn = element.getAnnotation( Inheritance.class );
|
||||||
MappedSuperclass mappedSuperClass = element.getAnnotation( MappedSuperclass.class );
|
MappedSuperclass mappedSuperClass = element.getAnnotation( MappedSuperclass.class );
|
||||||
if ( mappedSuperClass != null ) {
|
if ( mappedSuperClass != null ) {
|
||||||
isEmbeddableSuperclass = true;
|
setEmbeddableSuperclass( true );
|
||||||
type = inhAnn == null ? null : inhAnn.strategy();
|
setType( inhAnn == null ? null : inhAnn.strategy() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
type = inhAnn == null ? InheritanceType.SINGLE_TABLE : inhAnn.strategy();
|
setType( inhAnn == null ? InheritanceType.SINGLE_TABLE : inhAnn.strategy() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasTable() {
|
boolean hasTable() {
|
||||||
return !hasParents || !InheritanceType.SINGLE_TABLE.equals( type );
|
return !hasParents() || !InheritanceType.SINGLE_TABLE.equals( getType() );
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean hasDenormalizedTable() {
|
boolean hasDenormalizedTable() {
|
||||||
return hasParents && InheritanceType.TABLE_PER_CLASS.equals( type );
|
return hasParents() && InheritanceType.TABLE_PER_CLASS.equals( getType() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public static InheritanceState getSuperEntityInheritanceState(
|
public static InheritanceState getInheritanceStateOfSuperEntity(
|
||||||
XClass clazz, Map<XClass, InheritanceState> states,
|
XClass clazz, Map<XClass, InheritanceState> states,
|
||||||
ReflectionManager reflectionManager
|
ReflectionManager reflectionManager
|
||||||
) {
|
) {
|
||||||
|
@ -90,7 +92,9 @@ public class InheritanceState {
|
||||||
do {
|
do {
|
||||||
superclass = superclass.getSuperclass();
|
superclass = superclass.getSuperclass();
|
||||||
InheritanceState currentState = states.get( superclass );
|
InheritanceState currentState = states.get( superclass );
|
||||||
if ( currentState != null && !currentState.isEmbeddableSuperclass ) return currentState;
|
if ( currentState != null && !currentState.isEmbeddableSuperclass() ) {
|
||||||
|
return currentState;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
while ( superclass != null && !reflectionManager.equals( superclass, Object.class ) );
|
while ( superclass != null && !reflectionManager.equals( superclass, Object.class ) );
|
||||||
return null;
|
return null;
|
||||||
|
@ -109,4 +113,60 @@ public class InheritanceState {
|
||||||
while ( superclass != null && !reflectionManager.equals( superclass, Object.class ) );
|
while ( superclass != null && !reflectionManager.equals( superclass, Object.class ) );
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public XClass getClazz() {
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClazz(XClass clazz) {
|
||||||
|
this.clazz = clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasSiblings() {
|
||||||
|
return hasSiblings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHasSiblings(boolean hasSiblings) {
|
||||||
|
this.hasSiblings = hasSiblings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasParents() {
|
||||||
|
return hasParents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHasParents(boolean hasParents) {
|
||||||
|
this.hasParents = hasParents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InheritanceType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(InheritanceType type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmbeddableSuperclass() {
|
||||||
|
return isEmbeddableSuperclass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmbeddableSuperclass(boolean embeddableSuperclass) {
|
||||||
|
isEmbeddableSuperclass = embeddableSuperclass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAccessType() {
|
||||||
|
return accessType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccessType(String accessType) {
|
||||||
|
this.accessType = accessType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isPropertyAnnotated() {
|
||||||
|
return isPropertyAnnotated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPropertyAnnotated(Boolean propertyAnnotated) {
|
||||||
|
isPropertyAnnotated = propertyAnnotated;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -294,7 +294,7 @@ public class EntityBinder {
|
||||||
persistentClass.addTuplizer( mode, tuplizer.impl().getName() );
|
persistentClass.addTuplizer( mode, tuplizer.impl().getName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !inheritanceState.hasParents ) {
|
if ( !inheritanceState.hasParents() ) {
|
||||||
for ( Map.Entry<String, String> filter : filters.entrySet() ) {
|
for ( Map.Entry<String, String> filter : filters.entrySet() ) {
|
||||||
String filterName = filter.getKey();
|
String filterName = filter.getKey();
|
||||||
String cond = filter.getValue();
|
String cond = filter.getValue();
|
||||||
|
|
|
@ -21,7 +21,7 @@ public class AccessTest extends TestCase {
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.clear();
|
s.clear();
|
||||||
tx = s.beginTransaction();
|
tx = s.beginTransaction();
|
||||||
fur = (Furniture) s.get( Furniture.class, fur.getId() );
|
fur = ( Furniture ) s.get( Furniture.class, fur.getId() );
|
||||||
assertFalse( fur.isAlive );
|
assertFalse( fur.isAlive );
|
||||||
assertNotNull( fur.getColor() );
|
assertNotNull( fur.getColor() );
|
||||||
s.delete( fur );
|
s.delete( fur );
|
||||||
|
@ -38,7 +38,7 @@ public class AccessTest extends TestCase {
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.clear();
|
s.clear();
|
||||||
tx = s.beginTransaction();
|
tx = s.beginTransaction();
|
||||||
fur = (Furniture) s.get( Furniture.class, fur.getId() );
|
fur = ( Furniture ) s.get( Furniture.class, fur.getId() );
|
||||||
assertNotNull( fur.getGod() );
|
assertNotNull( fur.getGod() );
|
||||||
s.delete( fur );
|
s.delete( fur );
|
||||||
tx.commit();
|
tx.commit();
|
||||||
|
@ -54,12 +54,11 @@ public class AccessTest extends TestCase {
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.clear();
|
s.clear();
|
||||||
tx = s.beginTransaction();
|
tx = s.beginTransaction();
|
||||||
fur = (Furniture) s.get( Furniture.class, fur.getId() );
|
fur = ( Furniture ) s.get( Furniture.class, fur.getId() );
|
||||||
assertEquals( 5, fur.weight );
|
assertEquals( 5, fur.weight );
|
||||||
s.delete( fur );
|
s.delete( fur );
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.close();
|
s.close();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testNonOverridenSubclass() throws Exception {
|
public void testNonOverridenSubclass() throws Exception {
|
||||||
|
@ -71,12 +70,11 @@ public class AccessTest extends TestCase {
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.clear();
|
s.clear();
|
||||||
tx = s.beginTransaction();
|
tx = s.beginTransaction();
|
||||||
chair = (Chair) s.get( Chair.class, chair.getId() );
|
chair = ( Chair ) s.get( Chair.class, chair.getId() );
|
||||||
assertNull( chair.getPillow() );
|
assertNull( chair.getPillow() );
|
||||||
s.delete( chair );
|
s.delete( chair );
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.close();
|
s.close();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testOverridenSubclass() throws Exception {
|
public void testOverridenSubclass() throws Exception {
|
||||||
|
@ -89,13 +87,12 @@ public class AccessTest extends TestCase {
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.clear();
|
s.clear();
|
||||||
tx = s.beginTransaction();
|
tx = s.beginTransaction();
|
||||||
bed = (BigBed) s.get( BigBed.class, bed.getId() );
|
bed = ( BigBed ) s.get( BigBed.class, bed.getId() );
|
||||||
assertEquals( 5, bed.size );
|
assertEquals( 5, bed.size );
|
||||||
assertNull( bed.getQuality() );
|
assertNull( bed.getQuality() );
|
||||||
s.delete( bed );
|
s.delete( bed );
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.close();
|
s.close();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testFieldsOverriding() throws Exception {
|
public void testFieldsOverriding() throws Exception {
|
||||||
|
@ -107,22 +104,21 @@ public class AccessTest extends TestCase {
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.clear();
|
s.clear();
|
||||||
tx = s.beginTransaction();
|
tx = s.beginTransaction();
|
||||||
gs = (Gardenshed) s.get( Gardenshed.class, gs.getId() );
|
gs = ( Gardenshed ) s.get( Gardenshed.class, gs.getId() );
|
||||||
assertEquals( 4, gs.floors );
|
assertEquals( 4, gs.floors );
|
||||||
assertEquals( 6, gs.getFloors() );
|
assertEquals( 6, gs.getFloors() );
|
||||||
s.delete( gs );
|
s.delete( gs );
|
||||||
tx.commit();
|
tx.commit();
|
||||||
s.close();
|
s.close();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Class[] getMappings() {
|
protected Class[] getMappings() {
|
||||||
return new Class[]{
|
return new Class[] {
|
||||||
Bed.class,
|
Bed.class,
|
||||||
Chair.class,
|
Chair.class,
|
||||||
Furniture.class,
|
Furniture.class,
|
||||||
BigBed.class,
|
BigBed.class,
|
||||||
Gardenshed.class
|
Gardenshed.class,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@ public class Furniture extends Woody {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@AccessType("property")
|
@AccessType("property")
|
||||||
public long weight;
|
public long weight;
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@ import org.hibernate.annotations.AccessType;
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
*/
|
*/
|
||||||
@Embeddable
|
@Embeddable
|
||||||
//access = AccessType.PROPERTY)
|
|
||||||
@AccessType("property")
|
@AccessType("property")
|
||||||
public class Country implements Serializable {
|
public class Country implements Serializable {
|
||||||
private String iso2;
|
private String iso2;
|
||||||
|
@ -35,5 +34,4 @@ public class Country implements Serializable {
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue