HHH-4533 add representation for @MappedSuperclass in the Hibernate Core metamodel and properly populate this model extension in Hibernate Annotations

git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@17871 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
Emmanuel Bernard 2009-10-28 18:14:25 +00:00
parent 5cc638576f
commit c7c6981a55
24 changed files with 406 additions and 106 deletions

View File

@ -66,6 +66,10 @@ public abstract class AbstractPropertyHolder implements PropertyHolder {
return path;
}
protected ExtendedMappings getMappings() {
return mappings;
}
/**
* property can be null
*/

View File

@ -457,9 +457,10 @@ public final class AnnotationBinder {
}
XAnnotatedElement annotatedClass = clazzToProcess;
log.info( "Binding entity from annotated class: {}", clazzToProcess.getName() );
final ReflectionManager reflectionManager = mappings.getReflectionManager();
InheritanceState superEntityState =
InheritanceState.getSuperEntityInheritanceState(
clazzToProcess, inheritanceStatePerClass, mappings.getReflectionManager()
clazzToProcess, inheritanceStatePerClass, reflectionManager
);
PersistentClass superEntity = superEntityState != null ?
mappings.getClass(
@ -627,7 +628,7 @@ public final class AnnotationBinder {
PropertyHolder propertyHolder = PropertyHolderBuilder.buildPropertyHolder(
clazzToProcess,
persistentClass,
entityBinder, mappings
entityBinder, mappings, inheritanceStatePerClass
);
javax.persistence.SecondaryTable secTabAnn = annotatedClass.getAnnotation(
@ -702,7 +703,7 @@ public final class AnnotationBinder {
// check properties
List<PropertyData> elements =
getElementsToProcess(
clazzToProcess, inheritanceStatePerClass, propertyHolder, entityBinder, mappings
persistentClass, clazzToProcess, inheritanceStatePerClass, propertyHolder, entityBinder, mappings
);
if ( elements == null ) {
throw new AnnotationException( "No identifier specified for entity: " + propertyHolder.getEntityName() );
@ -724,13 +725,13 @@ public final class AnnotationBinder {
break;
}
state = InheritanceState.getSuperclassInheritanceState(
current, inheritanceStatePerClass, mappings.getReflectionManager()
current, inheritanceStatePerClass, reflectionManager
);
}
while ( state != null );
}
if ( idClass != null ) {
XClass compositeClass = mappings.getReflectionManager().toXClass( idClass.value() );
XClass compositeClass = reflectionManager.toXClass( idClass.value() );
boolean isComponent = true;
boolean propertyAnnotated = entityBinder.isPropertyAnnotated( compositeClass );
String propertyAccessor = entityBinder.getPropertyAccessor( compositeClass );
@ -757,7 +758,7 @@ public final class AnnotationBinder {
propertyAnnotated,
propertyAccessor, entityBinder,
true,
false, mappings
false, mappings, inheritanceStatePerClass
);
inferredData = new PropertyPreloadedData(
propertyAccessor, "_identifierMapper", compositeClass
@ -770,7 +771,7 @@ public final class AnnotationBinder {
propertyAccessor, false,
entityBinder,
true, true,
false, mappings
false, mappings, inheritanceStatePerClass
);
entityBinder.setIgnoreIdAnnotations( ignoreIdAnnotations );
persistentClass.setIdentifierMapper( mapper );
@ -800,7 +801,7 @@ public final class AnnotationBinder {
Nullability.NO_CONSTRAINT,
propertyAnnotatedElement.getProperty(),
propertyAnnotatedElement, classGenerators, entityBinder,
false, false, false, mappings
false, false, false, mappings, inheritanceStatePerClass
);
}
else {
@ -845,12 +846,13 @@ public final class AnnotationBinder {
* Change EntityBinder by side effect
*/
private static List<PropertyData> getElementsToProcess(
XClass clazzToProcess, Map<XClass, InheritanceState> inheritanceStatePerClass,
PersistentClass persistentClass, XClass clazzToProcess,
Map<XClass, InheritanceState> inheritanceStatePerClass,
PropertyHolder propertyHolder, EntityBinder entityBinder, ExtendedMappings mappings
) {
InheritanceState inheritanceState = inheritanceStatePerClass.get( clazzToProcess );
List<XClass> classesToProcess = orderClassesToBeProcessed(
clazzToProcess, inheritanceStatePerClass, inheritanceState, mappings
List<XClass> classesToProcess = getMappedSuperclassesTillNextEntityOrdered(
persistentClass, clazzToProcess, inheritanceStatePerClass, mappings
);
List<PropertyData> elements = new ArrayList<PropertyData>();
int deep = classesToProcess.size();
@ -858,7 +860,7 @@ public final class AnnotationBinder {
assert !inheritanceState.isEmbeddableSuperclass;
Boolean isExplicitPropertyAnnotated = null;
String explicitAccessType = null;
String explicitAccessType;
if ( inheritanceState.hasParents ) {
InheritanceState superEntityState =
InheritanceState.getSuperEntityInheritanceState(
@ -942,14 +944,17 @@ public final class AnnotationBinder {
null;
}
private static List<XClass> orderClassesToBeProcessed(
XClass annotatedClass, Map<XClass, InheritanceState> inheritanceStatePerClass,
InheritanceState inheritanceState, ExtendedMappings mappings
private static List<XClass> getMappedSuperclassesTillNextEntityOrdered(
PersistentClass persistentClass, XClass annotatedClass,
Map<XClass, InheritanceState> inheritanceStatePerClass,
ExtendedMappings mappings
) {
//ordered to allow proper messages on properties subclassing
List<XClass> classesToProcess = new ArrayList<XClass>();
XClass currentClassInHierarchy = annotatedClass;
InheritanceState superclassState;
final ReflectionManager reflectionManager = mappings.getReflectionManager();
do {
classesToProcess.add( 0, currentClassInHierarchy );
XClass superClass = currentClassInHierarchy;
@ -957,13 +962,36 @@ public final class AnnotationBinder {
superClass = superClass.getSuperclass();
superclassState = inheritanceStatePerClass.get( superClass );
}
while ( superClass != null && !mappings.getReflectionManager()
while ( superClass != null && !reflectionManager
.equals( superClass, Object.class ) && superclassState == null );
currentClassInHierarchy = superClass;
}
while ( superclassState != null && superclassState.isEmbeddableSuperclass );
//add @MappedSuperclass in the metadata
// classes from 0 to n-1 are @MappedSuperclass and should be linked
org.hibernate.mapping.MappedSuperclass mappedSuperclass = null;
final InheritanceState superEntityState =
InheritanceState.getSuperEntityInheritanceState(annotatedClass, inheritanceStatePerClass, reflectionManager);
PersistentClass superEntity =
superEntityState != null ?
mappings.getClass( superEntityState.clazz.getName() ) :
null;
final int lastMappedSuperclass = classesToProcess.size() - 1;
for ( int index = 0 ; index < lastMappedSuperclass ; index++ ) {
org.hibernate.mapping.MappedSuperclass parentSuperclass = mappedSuperclass;
final Class<?> type = mappings.getReflectionManager().toClass( classesToProcess.get( index ) );
//add MAppedSuperclass if not already there
mappedSuperclass = mappings.getMappedSuperclass( type );
if (mappedSuperclass == null) {
mappedSuperclass = new org.hibernate.mapping.MappedSuperclass(parentSuperclass, superEntity );
mappings.addMappedSuperclass( type, mappedSuperclass );
}
}
if (mappedSuperclass != null) {
persistentClass.setSuperMappedSuperclass(mappedSuperclass);
}
return classesToProcess;
}
@ -1127,7 +1155,7 @@ public final class AnnotationBinder {
" or set an explicit target attribute (eg @OneToMany(target=) or use an explicit @Type"
);
}
final boolean currentHasIdentifier = addProperty( p, elements, localPropertyAccessor, mappings );
final boolean currentHasIdentifier = addProperty( annotatedClass, p, elements, localPropertyAccessor, mappings );
hasIdentifier = hasIdentifier || currentHasIdentifier;
}
return hasIdentifier;
@ -1173,17 +1201,17 @@ public final class AnnotationBinder {
}
private static boolean addProperty(
XProperty property, List<PropertyData> annElts,
XClass declaringClass, XProperty property, List<PropertyData> annElts,
String propertyAccessor, ExtendedMappings mappings
) {
boolean hasIdentifier = false;
PropertyData propertyAnnotatedElement = new PropertyInferredData(
property, propertyAccessor,
declaringClass, property, propertyAccessor,
mappings.getReflectionManager() );
if ( !mustBeSkipped( propertyAnnotatedElement.getProperty(), mappings ) ) {
/*
* put element annotated by @Id in front
* since it has to be parsed before any assoctation by Hibernate
* since it has to be parsed before any association by Hibernate
*/
final XAnnotatedElement element = propertyAnnotatedElement.getProperty();
if ( element.isAnnotationPresent( Id.class ) || element.isAnnotationPresent( EmbeddedId.class ) ) {
@ -1212,7 +1240,8 @@ public final class AnnotationBinder {
PropertyHolder propertyHolder, Nullability nullability, XProperty property,
PropertyData inferredData, HashMap<String, IdGenerator> classGenerators,
EntityBinder entityBinder, boolean isIdentifierMapper,
boolean isComponentEmbedded, boolean inSecondPass, ExtendedMappings mappings
boolean isComponentEmbedded, boolean inSecondPass, ExtendedMappings mappings,
Map<XClass, InheritanceState> inheritanceStatePerClass
)
throws MappingException {
/**
@ -1389,7 +1418,9 @@ public final class AnnotationBinder {
propertyAnnotated,
propertyAccessor, entityBinder,
false,
isIdentifierMapper, mappings
isIdentifierMapper,
mappings,
inheritanceStatePerClass
);
log.debug(
@ -1426,7 +1457,7 @@ public final class AnnotationBinder {
propBinder.setProperty( property );
propBinder.setReturnedClass( inferredData.getPropertyClass() );
propBinder.setMappings( mappings );
propBinder.setDeclaringClass( inferredData.getDeclaringClass() );
Property prop = propBinder.bind();
propBinder.getSimpleValueBinder().setVersion(true);
rootClass.setVersion( prop );
@ -1791,6 +1822,8 @@ public final class AnnotationBinder {
collectionBinder.setLocalGenerators( localGenerators );
}
collectionBinder.setInheritanceStatePerClass( inheritanceStatePerClass );
collectionBinder.setDeclaringClass( inferredData.getDeclaringClass() );
collectionBinder.bind();
}
@ -1810,7 +1843,7 @@ public final class AnnotationBinder {
bindComponent(
inferredData, propertyHolder, propertyAnnotated, propertyAccessor, entityBinder,
isIdentifierMapper,
mappings, isComponentEmbedded
mappings, isComponentEmbedded, inheritanceStatePerClass
);
}
else {
@ -1844,6 +1877,7 @@ public final class AnnotationBinder {
propBinder.setInsertable( false );
propBinder.setUpdatable( false );
}
propBinder.setDeclaringClass( inferredData.getDeclaringClass() );
propBinder.bind();
}
}
@ -1955,12 +1989,13 @@ public final class AnnotationBinder {
boolean propertyAnnotated,
String propertyAccessor, EntityBinder entityBinder,
boolean isIdentifierMapper,
ExtendedMappings mappings, boolean isComponentEmbedded
ExtendedMappings mappings, boolean isComponentEmbedded,
Map<XClass, InheritanceState> inheritanceStatePerClass
) {
Component comp = fillComponent(
propertyHolder, inferredData, propertyAnnotated, propertyAccessor, true, entityBinder,
isComponentEmbedded, isIdentifierMapper,
false, mappings
false, mappings, inheritanceStatePerClass
);
XProperty property = inferredData.getProperty();
setupComponentTuplizer( property, comp );
@ -1971,24 +2006,28 @@ public final class AnnotationBinder {
binder.setProperty( inferredData.getProperty() );
binder.setPropertyAccessorName( inferredData.getDefaultAccess() );
Property prop = binder.make();
propertyHolder.addProperty( prop );
propertyHolder.addProperty( prop, inferredData.getDeclaringClass() );
}
public static Component fillComponent(
PropertyHolder propertyHolder, PropertyData inferredData,
boolean propertyAnnotated, String propertyAccessor, boolean isNullable,
EntityBinder entityBinder,
boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass, ExtendedMappings mappings
boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass,
ExtendedMappings mappings, Map<XClass, InheritanceState> inheritanceStatePerClass
) {
return fillComponent(propertyHolder, inferredData, null, propertyAnnotated, propertyAccessor, isNullable, entityBinder, isComponentEmbedded, isIdentifierMapper, inSecondPass, mappings);
return fillComponent(propertyHolder, inferredData, null, propertyAnnotated, propertyAccessor,
isNullable, entityBinder, isComponentEmbedded, isIdentifierMapper, inSecondPass, mappings,
inheritanceStatePerClass);
}
public static Component fillComponent(
PropertyHolder propertyHolder, PropertyData inferredData, PropertyData baseInferredData,
boolean propertyAnnotated, String propertyAccessor, boolean isNullable,
EntityBinder entityBinder,
boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass, ExtendedMappings mappings
boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass, ExtendedMappings mappings,
Map<XClass, InheritanceState> inheritanceStatePerClass
) {
/**
@ -2057,15 +2096,12 @@ public final class AnnotationBinder {
);
superClass = superClass.getSuperclass();
}
if(baseClassElements != null)
{
if(!hasIdClassAnnotations(inferredData.getPropertyClass()))
{
for(int i=0; i < classElements.size(); i++)
{
classElements.set(i, baseClassElements.get(i)); //this works since they are in the same order
}
}
if ( baseClassElements != null ) {
if ( !hasIdClassAnnotations( inferredData.getPropertyClass() ) ) {
for ( int i = 0; i < classElements.size(); i++ ) {
classElements.set( i, baseClassElements.get( i ) ); //this works since they are in the same order
}
}
}
for (PropertyData propertyAnnotatedElement : classElements) {
processElementAnnotations(
@ -2074,7 +2110,7 @@ public final class AnnotationBinder {
Nullability.FORCED_NOT_NULL,
propertyAnnotatedElement.getProperty(), propertyAnnotatedElement,
new HashMap<String, IdGenerator>(), entityBinder, isIdentifierMapper, isComponentEmbedded,
inSecondPass, mappings
inSecondPass, mappings, inheritanceStatePerClass
);
}
return comp;
@ -2087,10 +2123,13 @@ public final class AnnotationBinder {
boolean isComposite,
boolean isPropertyAnnotated,
String propertyAccessor, EntityBinder entityBinder, boolean isEmbedded,
boolean isIdentifierMapper, ExtendedMappings mappings
boolean isIdentifierMapper, ExtendedMappings mappings,
Map<XClass, InheritanceState> inheritanceStatePerClass
) {
bindId(generatorType, generatorName, inferredData, null, columns, propertyHolder, localGenerators, isComposite, isPropertyAnnotated, propertyAccessor, entityBinder, isEmbedded, isIdentifierMapper, mappings);
bindId(generatorType, generatorName, inferredData, null, columns, propertyHolder,
localGenerators, isComposite, isPropertyAnnotated, propertyAccessor, entityBinder,
isEmbedded, isIdentifierMapper, mappings, inheritanceStatePerClass);
}
private static void bindId(
@ -2100,7 +2139,8 @@ public final class AnnotationBinder {
boolean isComposite,
boolean isPropertyAnnotated,
String propertyAccessor, EntityBinder entityBinder, boolean isEmbedded,
boolean isIdentifierMapper, ExtendedMappings mappings
boolean isIdentifierMapper, ExtendedMappings mappings,
Map<XClass, InheritanceState> inheritanceStatePerClass
) {
/*
@ -2121,7 +2161,7 @@ public final class AnnotationBinder {
if ( isComposite ) {
id = fillComponent(
propertyHolder, inferredData, baseInferredData, isPropertyAnnotated, propertyAccessor,
false, entityBinder, isEmbedded, isIdentifierMapper, false, mappings
false, entityBinder, isEmbedded, isIdentifierMapper, false, mappings, inheritanceStatePerClass
);
Component componentId = (Component) id;
componentId.setKey( true );
@ -2247,7 +2287,7 @@ public final class AnnotationBinder {
binder.setProperty(inferredData.getProperty());
Property prop = binder.make();
//composite FK columns are in the same table so its OK
propertyHolder.addProperty( prop, columns );
propertyHolder.addProperty( prop, columns, inferredData.getDeclaringClass() );
}
protected static void defineFetchingStrategy(ToOne toOne, XProperty property) {
@ -2397,7 +2437,7 @@ public final class AnnotationBinder {
binder.setCascade( cascadeStrategy );
Property prop = binder.make();
//composite FK columns are in the same table so its OK
propertyHolder.addProperty( prop, columns );
propertyHolder.addProperty( prop, columns, inferredData.getDeclaringClass() );
}
private static String generatorType(GenerationType generatorEnum) {

View File

@ -135,6 +135,7 @@ public class AnnotationConfiguration extends Configuration {
private transient ReflectionManager reflectionManager;
private boolean isDefaultProcessed = false;
private boolean isValidatorNotPresentLogged;
private Map<Class<?>, org.hibernate.mapping.MappedSuperclass> mappedSuperclasses;
public AnnotationConfiguration() {
super();
@ -260,6 +261,7 @@ public class AnnotationConfiguration extends Configuration {
namingStrategy = EJB3NamingStrategy.INSTANCE;
setEntityResolver( new EJB3DTDEntityResolver() );
anyMetaDefs = new HashMap<String, AnyMetaDef>();
mappedSuperclasses = new HashMap<Class<?>, org.hibernate.mapping.MappedSuperclass>();
reflectionManager = new JavaReflectionManager();
( ( MetadataProviderInjector ) reflectionManager ).setMetadataProvider( new JPAMetadataProvider() );
@ -1178,6 +1180,13 @@ public class AnnotationConfiguration extends Configuration {
return inSecondPass;
}
public void addMappedSuperclass(Class<?> type, org.hibernate.mapping.MappedSuperclass mappedSuperclass) {
mappedSuperclasses.put( type, mappedSuperclass );
}
public org.hibernate.mapping.MappedSuperclass getMappedSuperclass(Class<?> type) {
return mappedSuperclasses.get( type );
}
public IdGenerator getGenerator(String name) {
return getGenerator( name, null );
@ -1240,6 +1249,7 @@ public class AnnotationConfiguration extends Configuration {
}
}
//FIXME should be private but is part of the ExtendedMapping contract
public AnnotatedClassType addClassType(XClass clazz) {
AnnotatedClassType type;
if ( clazz.isAnnotationPresent( Entity.class ) ) {

View File

@ -28,6 +28,7 @@ import java.util.Map;
import javax.persistence.JoinTable;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.AssertionFailure;
import org.hibernate.cfg.annotations.EntityBinder;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.Join;
@ -35,6 +36,7 @@ import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Table;
import org.hibernate.mapping.MappedSuperclass;
/**
* @author Emmanuel Bernard
@ -44,20 +46,23 @@ public class ClassPropertyHolder extends AbstractPropertyHolder {
private Map<String, Join> joins;
private transient Map<String, Join> joinsPerRealTableName;
private EntityBinder entityBinder;
private final Map<XClass, InheritanceState> inheritanceStatePerClass;
public ClassPropertyHolder(
PersistentClass persistentClass, XClass clazzToProcess, Map<String, Join> joins, ExtendedMappings mappings
PersistentClass persistentClass, XClass clazzToProcess,
Map<String, Join> joins, ExtendedMappings mappings, Map<XClass, InheritanceState> inheritanceStatePerClass
) {
super( persistentClass.getEntityName(), null, clazzToProcess, mappings );
this.persistentClass = persistentClass;
this.joins = joins;
this.inheritanceStatePerClass = inheritanceStatePerClass;
}
public ClassPropertyHolder(
PersistentClass persistentClass, XClass clazzToProcess, EntityBinder entityBinder,
ExtendedMappings mappings
ExtendedMappings mappings, Map<XClass, InheritanceState> inheritanceStatePerClass
) {
this( persistentClass, clazzToProcess, entityBinder.getSecondaryTables(), mappings );
this( persistentClass, clazzToProcess, entityBinder.getSecondaryTables(), mappings, inheritanceStatePerClass );
this.entityBinder = entityBinder;
}
@ -65,14 +70,32 @@ public class ClassPropertyHolder extends AbstractPropertyHolder {
return persistentClass.getEntityName();
}
public void addProperty(Property prop, Ejb3Column[] columns) {
public void addProperty(Property prop, Ejb3Column[] columns, XClass declaringClass) {
//Ejb3Column.checkPropertyConsistency( ); //already called earlier
if ( columns[0].isSecondary() ) {
//TODO move the getJoin() code here?
columns[0].getJoin().addProperty( prop );
final Join join = columns[0].getJoin();
addPropertyToJoin( prop, declaringClass, join );
}
else {
addProperty( prop );
addProperty( prop, declaringClass );
}
}
public void addProperty(Property prop, XClass declaringClass) {
if ( prop.getValue() instanceof Component ) {
//TODO handle quote and non quote table comparison
String tableName = prop.getValue().getTable().getName();
if ( getJoinsPerRealTableName().containsKey( tableName ) ) {
final Join join = getJoinsPerRealTableName().get( tableName );
addPropertyToJoin( prop, declaringClass, join );
}
else {
addPropertyToPersistentClass( prop, declaringClass );
}
}
else {
addPropertyToPersistentClass( prop, declaringClass );
}
}
@ -82,12 +105,17 @@ public class ClassPropertyHolder extends AbstractPropertyHolder {
return join;
}
public void addProperty(Property prop) {
if ( prop.getValue() instanceof Component ) {
//TODO handle quote and non quote table comparison
String tableName = prop.getValue().getTable().getName();
if ( getJoinsPerRealTableName().containsKey( tableName ) ) {
getJoinsPerRealTableName().get( tableName ).addProperty( prop );
private void addPropertyToPersistentClass(Property prop, XClass declaringClass) {
if ( declaringClass != null ) {
final InheritanceState inheritanceState = inheritanceStatePerClass.get( declaringClass );
if ( inheritanceState == null ) {
throw new AssertionFailure(
"Declaring class is not found in the inheritance state hierarchy: " + declaringClass
);
}
if ( inheritanceState.isEmbeddableSuperclass ) {
persistentClass.addMappedsuperclassProperty(prop);
addPropertyToMappedSuperclass( prop, declaringClass );
}
else {
persistentClass.addProperty( prop );
@ -98,6 +126,34 @@ public class ClassPropertyHolder extends AbstractPropertyHolder {
}
}
private void addPropertyToMappedSuperclass(Property prop, XClass declaringClass) {
final ExtendedMappings mappings = getMappings();
final Class type = mappings.getReflectionManager().toClass( declaringClass );
MappedSuperclass superclass = mappings.getMappedSuperclass( type );
superclass.addProperty( prop );
}
private void addPropertyToJoin(Property prop, XClass declaringClass, Join join) {
if ( declaringClass != null ) {
final InheritanceState inheritanceState = inheritanceStatePerClass.get( declaringClass );
if ( inheritanceState == null ) {
throw new AssertionFailure(
"Declaring class is not found in the inheritance state hierarchy: " + declaringClass
);
}
if ( inheritanceState.isEmbeddableSuperclass ) {
join.addMappedsuperclassProperty(prop);
addPropertyToMappedSuperclass( prop, declaringClass );
}
else {
join.addProperty( prop );
}
}
else {
join.addProperty( prop );
}
}
/**
* Needed for proper compliance with naming strategy, the property table
* can be overriden if the properties are part of secondary tables

View File

@ -62,7 +62,7 @@ public class CollectionPropertyHolder extends AbstractPropertyHolder {
return collection.getCollectionTable();
}
public void addProperty(Property prop) {
public void addProperty(Property prop, XClass declaringClass) {
throw new AssertionFailure( "Cannot add property to a collection" );
}
@ -86,7 +86,7 @@ public class CollectionPropertyHolder extends AbstractPropertyHolder {
return collection.getOwner().getEntityName();
}
public void addProperty(Property prop, Ejb3Column[] columns) {
public void addProperty(Property prop, Ejb3Column[] columns, XClass declaringClass) {
//Ejb3Column.checkPropertyConsistency( ); //already called earlier
throw new AssertionFailure( "addProperty to a join table of a collection: does it make sense?" );
}

View File

@ -28,6 +28,7 @@ import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import org.hibernate.AnnotationException;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.Join;
import org.hibernate.mapping.KeyValue;
@ -49,7 +50,7 @@ public class ComponentPropertyHolder extends AbstractPropertyHolder {
return component.getComponentClassName();
}
public void addProperty(Property prop, Ejb3Column[] columns) {
public void addProperty(Property prop, Ejb3Column[] columns, XClass declaringClass) {
//Ejb3Column.checkPropertyConsistency( ); //already called earlier
/*
* Check table matches between the component and the columns
@ -68,7 +69,7 @@ public class ComponentPropertyHolder extends AbstractPropertyHolder {
);
}
}
addProperty( prop );
addProperty( prop, declaringClass );
}
public Join addJoin(JoinTable joinTableAnn, boolean noDelayInPkColumnCreation) {
@ -97,7 +98,7 @@ public class ComponentPropertyHolder extends AbstractPropertyHolder {
return component.getTable();
}
public void addProperty(Property prop) {
public void addProperty(Property prop, XClass declaringClass) {
component.addProperty( prop );
}

View File

@ -36,6 +36,7 @@ import org.hibernate.util.StringHelper;
import org.hibernate.annotations.JoinColumnOrFormula;
import org.hibernate.annotations.JoinColumnsOrFormulas;
import org.hibernate.annotations.JoinFormula;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.mapping.Column;
import org.hibernate.mapping.Join;
import org.hibernate.mapping.PersistentClass;
@ -355,9 +356,11 @@ public class Ejb3JoinColumn extends Ejb3Column {
* Override persistent class on oneToMany Cases for late settings
* Must only be used on second level pass binding
*/
public void setPersistentClass(PersistentClass persistentClass, Map<String, Join> joins) {
public void setPersistentClass(PersistentClass persistentClass,
Map<String, Join> joins,
Map<XClass, InheritanceState> inheritanceStatePerClass) {
//FIXME shouldn't we deduce the classname from the persistentclasS?
this.propertyHolder = PropertyHolderBuilder.buildPropertyHolder( persistentClass, joins, getMappings() );
this.propertyHolder = PropertyHolderBuilder.buildPropertyHolder( persistentClass, joins, getMappings(), inheritanceStatePerClass );
}
public static void checkIfJoinColumn(Object columns, PropertyHolder holder, PropertyData property) {

View File

@ -27,6 +27,8 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.persistence.MappedSuperclass;
import org.hibernate.AnnotationException;
import org.hibernate.MappingException;
import org.hibernate.annotations.AnyMetaDef;
@ -124,6 +126,7 @@ public interface ExtendedMappings extends Mappings {
public AnnotatedClassType getClassType(XClass clazz);
/**
* FIXME should be private but will this break things?
* Add a class type.
*
* @param clazz The XClass mapping.
@ -157,6 +160,15 @@ public interface ExtendedMappings extends Mappings {
public AnyMetaDef getAnyMetaDef(String name);
public boolean isInSecondPass();
public boolean isInSecondPass();
/**
* add a new MappedSuperclass
*/
public void addMappedSuperclass(Class<?> type, org.hibernate.mapping.MappedSuperclass mappedSuperclass);
/**
* Get a MappedSuperclass or null if not mapped
*/
org.hibernate.mapping.MappedSuperclass getMappedSuperclass(Class<?> type);
}

View File

@ -131,7 +131,7 @@ public class OneToOneSecondPass implements SecondPass {
path, mappings
) ).doSecondPass( persistentClasses );
//no column associated since its a one to one
propertyHolder.addProperty( prop );
propertyHolder.addProperty( prop, inferredData.getDeclaringClass() );
}
else {
//this is a many to one with Formula
@ -162,7 +162,7 @@ public class OneToOneSecondPass implements SecondPass {
);
}
if ( otherSideProperty.getValue() instanceof OneToOne ) {
propertyHolder.addProperty( prop );
propertyHolder.addProperty( prop, inferredData.getDeclaringClass() );
}
else if ( otherSideProperty.getValue() instanceof ManyToOne ) {
Iterator it = otherSide.getJoinIterator();
@ -208,7 +208,7 @@ public class OneToOneSecondPass implements SecondPass {
mappedByJoin.addProperty( prop );
}
else {
propertyHolder.addProperty( prop );
propertyHolder.addProperty( prop, inferredData.getDeclaringClass() );
}
value.setReferencedPropertyName( mappedBy );

View File

@ -33,33 +33,43 @@ public interface PropertyData {
* @return default member access (whether field or property)
* @throws MappingException No getter or field found or wrong JavaBean spec usage
*/
public String getDefaultAccess();
String getDefaultAccess();
/**
* @return property name
* @throws MappingException No getter or field found or wrong JavaBean spec usage
*/
public String getPropertyName() throws MappingException;
String getPropertyName() throws MappingException;
/**
* Returns the returned class itself or the element type if an array
*/
public XClass getClassOrElement() throws MappingException;
XClass getClassOrElement() throws MappingException;
/**
* Return the class itself
*/
public XClass getPropertyClass() throws MappingException;
XClass getPropertyClass() throws MappingException;
/**
* Returns the returned class name itself or the element type if an array
*/
public String getClassOrElementName() throws MappingException;
String getClassOrElementName() throws MappingException;
/**
* Returns the returned class name itself
*/
public String getTypeName() throws MappingException;
String getTypeName() throws MappingException;
public XProperty getProperty();
/**
* Return the Hibernate mapping property
*/
XProperty getProperty();
/**
* Return the Class the property is declared on
* If the property is declared on a @MappedSuperclass,
* this class will be different than the PersistentClass's class
*/
XClass getDeclaringClass();
}

View File

@ -32,6 +32,7 @@ import org.hibernate.mapping.KeyValue;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Table;
import org.hibernate.annotations.common.reflection.XClass;
/**
* Property holder abstract property containers from their direct implementation
@ -45,7 +46,9 @@ public interface PropertyHolder {
Table getTable();
void addProperty(Property prop);
void addProperty(Property prop, XClass declaringClass);
void addProperty(Property prop, Ejb3Column[] columns, XClass declaringClass);
KeyValue getIdentifier();
@ -71,7 +74,5 @@ public interface PropertyHolder {
String getEntityName();
void addProperty(Property prop, Ejb3Column[] columns);
Join addJoin(JoinTable joinTableAnn, boolean noDelayInPkColumnCreation);
}

View File

@ -47,9 +47,10 @@ public final class PropertyHolderBuilder {
PersistentClass persistentClass,
EntityBinder entityBinder,
//Map<String, Join> joins,
ExtendedMappings mappings
ExtendedMappings mappings,
Map<XClass, InheritanceState> inheritanceStatePerClass
) {
return new ClassPropertyHolder( persistentClass, clazzToProcess, entityBinder, mappings );
return new ClassPropertyHolder( persistentClass, clazzToProcess, entityBinder, mappings, inheritanceStatePerClass );
}
/**
@ -82,8 +83,9 @@ public final class PropertyHolderBuilder {
*/
public static PropertyHolder buildPropertyHolder(
PersistentClass persistentClass, Map<String, Join> joins,
ExtendedMappings mappings
ExtendedMappings mappings,
Map<XClass, InheritanceState> inheritanceStatePerClass
) {
return new ClassPropertyHolder( persistentClass, null, joins, mappings );
return new ClassPropertyHolder( persistentClass, null, joins, mappings, inheritanceStatePerClass );
}
}

View File

@ -41,11 +41,14 @@ public class PropertyInferredData implements PropertyData {
private final XProperty property;
private final ReflectionManager reflectionManager;
private final XClass declaringClass;
/**
* Take the annoted element for lazy process
*/
public PropertyInferredData(XProperty property, String propertyAccessor, ReflectionManager reflectionManager) {
public PropertyInferredData(XClass declaringClass, XProperty property, String propertyAccessor, ReflectionManager reflectionManager) {
this.declaringClass = declaringClass;
this.property = property;
this.defaultAccess = propertyAccessor;
this.reflectionManager = reflectionManager;
@ -91,4 +94,8 @@ public class PropertyInferredData implements PropertyData {
public XProperty getProperty() {
return property;
}
public XClass getDeclaringClass() {
return declaringClass;
}
}

View File

@ -67,4 +67,10 @@ public class PropertyPreloadedData implements PropertyData {
public XProperty getProperty() {
return null; //instead of UnsupportedOperationException
}
public XClass getDeclaringClass() {
//Preloaded properties are artificial wrapper for colleciton element accesses
//and idClass creation, ignore.
return null;
}
}

View File

@ -51,6 +51,10 @@ public class WrappedInferredData implements PropertyData {
return wrappedInferredData.getProperty();
}
public XClass getDeclaringClass() {
return wrappedInferredData.getDeclaringClass();
}
public XClass getPropertyClass() throws MappingException {
return wrappedInferredData.getPropertyClass();
}

View File

@ -32,17 +32,19 @@ import java.util.Map;
import java.util.StringTokenizer;
import javax.persistence.AttributeOverride;
import javax.persistence.AttributeOverrides;
import javax.persistence.ElementCollection;
import javax.persistence.Embeddable;
import javax.persistence.FetchType;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.MapKey;
import javax.persistence.OneToMany;
import javax.persistence.ElementCollection;
import javax.persistence.MapKeyColumn;
import javax.persistence.OneToMany;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.FetchMode;
import org.hibernate.MappingException;
import org.hibernate.annotations.BatchSize;
@ -71,6 +73,7 @@ import org.hibernate.annotations.Sort;
import org.hibernate.annotations.SortType;
import org.hibernate.annotations.Where;
import org.hibernate.annotations.WhereJoinTable;
import org.hibernate.annotations.common.AssertionFailure;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.cfg.AnnotatedClassType;
@ -81,6 +84,7 @@ import org.hibernate.cfg.Ejb3Column;
import org.hibernate.cfg.Ejb3JoinColumn;
import org.hibernate.cfg.ExtendedMappings;
import org.hibernate.cfg.IndexColumn;
import org.hibernate.cfg.InheritanceState;
import org.hibernate.cfg.PropertyData;
import org.hibernate.cfg.PropertyHolder;
import org.hibernate.cfg.PropertyHolderBuilder;
@ -105,8 +109,6 @@ import org.hibernate.mapping.SimpleValue;
import org.hibernate.mapping.SingleTableSubclass;
import org.hibernate.mapping.Table;
import org.hibernate.util.StringHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Base class for binding different types of collections to Hibernate configuration objects.
@ -152,11 +154,18 @@ public abstract class CollectionBinder {
private Ejb3Column[] mapKeyColumns;
private Ejb3JoinColumn[] mapKeyManyToManyColumns;
protected HashMap<String, IdGenerator> localGenerators;
protected Map<XClass, InheritanceState> inheritanceStatePerClass;
private XClass declaringClass;
private boolean declaringClassSet;
public void setUpdatable(boolean updatable) {
this.updatable = updatable;
}
public void setInheritanceStatePerClass(Map<XClass, InheritanceState> inheritanceStatePerClass) {
this.inheritanceStatePerClass = inheritanceStatePerClass;
}
public void setInsertable(boolean insertable) {
this.insertable = insertable;
}
@ -333,6 +342,11 @@ public abstract class CollectionBinder {
this.propertyName = propertyName;
}
public void setDeclaringClass(XClass declaringClass) {
this.declaringClass = declaringClass;
this.declaringClassSet = true;
}
public void bind() {
this.collection = createCollection( propertyHolder.getPersistentClass() );
log.debug( "Collection role: {}", StringHelper.qualify( propertyHolder.getPath(), propertyName ) );
@ -443,6 +457,7 @@ public abstract class CollectionBinder {
}
//TODO reducce tableBinder != null and oneToMany
XClass collectionType = getCollectionType();
if ( inheritanceStatePerClass == null) throw new AssertionFailure( "inheritanceStatePerClass not set" );
SecondPass sp = getSecondPass(
fkJoinColumns,
joinColumns,
@ -482,7 +497,8 @@ public abstract class CollectionBinder {
binder.setUpdatable( updatable );
Property prop = binder.make();
//we don't care about the join stuffs because the column is on the association table.
propertyHolder.addProperty( prop );
if (! declaringClassSet) throw new AssertionFailure( "DeclaringClass is not set in CollectionBinder while binding" );
propertyHolder.addProperty( prop, declaringClass );
}
private void defineFetchingStrategy() {
@ -569,7 +585,6 @@ public abstract class CollectionBinder {
final boolean ignoreNotFound, final boolean unique,
final TableBinder assocTableBinder, final ExtendedMappings mappings
) {
return new CollectionSecondPass( mappings, collection ) {
public void secondPass(java.util.Map persistentClasses, java.util.Map inheritedMetas)
@ -591,7 +606,8 @@ public abstract class CollectionBinder {
Ejb3JoinColumn[] keyColumns, Ejb3JoinColumn[] inverseColumns, Ejb3Column[] elementColumns,
boolean isEmbedded,
XProperty property, boolean unique,
TableBinder associationTableBinder, boolean ignoreNotFound, ExtendedMappings mappings
TableBinder associationTableBinder,
boolean ignoreNotFound, ExtendedMappings mappings
) {
PersistentClass persistentClass = (PersistentClass) persistentClasses.get( collType.getName() );
boolean reversePropertyInJoin = false;
@ -627,7 +643,8 @@ public abstract class CollectionBinder {
collType,
cascadeDeleteEnabled,
ignoreNotFound, hqlOrderBy,
mappings
mappings,
inheritanceStatePerClass
);
return true;
}
@ -651,7 +668,8 @@ public abstract class CollectionBinder {
protected void bindOneToManySecondPass(
Collection collection, Map persistentClasses, Ejb3JoinColumn[] fkJoinColumns,
XClass collectionType,
boolean cascadeDeleteEnabled, boolean ignoreNotFound, String hqlOrderBy, ExtendedMappings extendedMappings
boolean cascadeDeleteEnabled, boolean ignoreNotFound, String hqlOrderBy, ExtendedMappings extendedMappings,
Map<XClass, InheritanceState> inheritanceStatePerClass
) {
log.debug("Binding a OneToMany: {}.{} through a foreign key", propertyHolder.getEntityName(), propertyName);
@ -677,7 +695,7 @@ public abstract class CollectionBinder {
}
oneToMany.setAssociatedClass( associatedClass );
for (Ejb3JoinColumn column : fkJoinColumns) {
column.setPersistentClass( associatedClass, joins );
column.setPersistentClass( associatedClass, joins, inheritanceStatePerClass );
column.setJoins( joins );
collection.setCollectionTable( column.getTable() );
}
@ -1221,7 +1239,7 @@ public abstract class CollectionBinder {
else if ( anyAnn != null ) {
//@ManyToAny
//Make sure that collTyp is never used during the @ManyToAny branch: it will be set to void.class
PropertyData inferredData = new PropertyInferredData( property, "unsupported", mappings.getReflectionManager() );
PropertyData inferredData = new PropertyInferredData(null, property, "unsupported", mappings.getReflectionManager() );
//override the table
for (Ejb3Column column : inverseJoinColumns) {
column.setTable( collValue.getCollectionTable() );
@ -1284,7 +1302,7 @@ public abstract class CollectionBinder {
Component component = AnnotationBinder.fillComponent(
holder, inferredData, isPropertyAnnotated, isPropertyAnnotated ? "property" : "field", true,
entityBinder, false, false,
true, mappings
true, mappings, inheritanceStatePerClass
);
collValue.setElement( component );

View File

@ -68,7 +68,7 @@ public class IdBagBinder extends BagBinder {
SimpleValueBinder simpleValue = new SimpleValueBinder();
PropertyData propertyData = new WrappedInferredData(
new PropertyInferredData( property, null, //default access should not be useful
new PropertyInferredData( null, property, null, //default access should not be useful
mappings.getReflectionManager() ),
"id" );
Ejb3Column[] idColumns = Ejb3Column.buildColumnFromAnnotation(

View File

@ -25,13 +25,15 @@ package org.hibernate.cfg.annotations;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.AnnotationException;
import org.hibernate.MappingException;
import org.hibernate.annotations.OrderBy;
import org.hibernate.annotations.Sort;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.util.StringHelper;
import org.hibernate.cfg.CollectionSecondPass;
import org.hibernate.cfg.Ejb3Column;
import org.hibernate.cfg.Ejb3JoinColumn;
@ -45,8 +47,7 @@ import org.hibernate.mapping.List;
import org.hibernate.mapping.OneToMany;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.SimpleValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.hibernate.util.StringHelper;
/**
* Bind a list to the underlying Hibernate configuration

View File

@ -35,8 +35,8 @@ import org.hibernate.AnnotationException;
import org.hibernate.AssertionFailure;
import org.hibernate.FetchMode;
import org.hibernate.MappingException;
import org.hibernate.annotations.MapKeyManyToMany;
import org.hibernate.annotations.MapKey;
import org.hibernate.annotations.MapKeyManyToMany;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.cfg.AnnotatedClassType;
@ -232,7 +232,7 @@ public class MapBinder extends CollectionBinder {
Component component = AnnotationBinder.fillComponent(
holder, inferredData, isPropertyAnnotated, isPropertyAnnotated ? "property" : "field", true,
entityBinder, false, false,
true, mappings
true, mappings, inheritanceStatePerClass
);
mapValue.setIndex( component );
}

View File

@ -34,6 +34,7 @@ import org.hibernate.annotations.NaturalId;
import org.hibernate.annotations.OptimisticLock;
import org.hibernate.annotations.common.reflection.XClass;
import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.annotations.common.AssertionFailure;
import org.hibernate.cfg.Ejb3Column;
import org.hibernate.cfg.ExtendedMappings;
import org.hibernate.cfg.PropertyHolder;
@ -62,6 +63,8 @@ public class PropertyBinder {
private boolean updatable = true;
private String cascade;
private SimpleValueBinder simpleValueBinder;
private XClass declaringClass;
private boolean declaringClassSet;
/*
* property can be null
@ -118,11 +121,19 @@ public class PropertyBinder {
this.mappings = mappings;
}
public void setDeclaringClass(XClass declaringClass) {
this.declaringClass = declaringClass;
this.declaringClassSet = true;
}
private void validateBind() {
if (property.isAnnotationPresent(Immutable.class)) {
throw new AnnotationException("@Immutable on property not allowed. " +
"Only allowed on entity level or on a collection.");
}
}
if ( !declaringClassSet ) {
throw new AssertionFailure( "declaringClass has not been set before a bind");
}
}
private void validateMake() {
@ -146,7 +157,7 @@ public class PropertyBinder {
SimpleValue propertyValue = simpleValueBinder.make();
setValue( propertyValue );
Property prop = make();
holder.addProperty( prop, columns );
holder.addProperty( prop, columns, declaringClass );
return prop;
}

View File

@ -39,6 +39,7 @@ public class Join implements Serializable {
private static final Alias PK_ALIAS = new Alias(15, "PK");
private ArrayList properties = new ArrayList();
private ArrayList declaredProperties = new ArrayList();
private Table table;
private KeyValue key;
private PersistentClass persistentClass;
@ -59,8 +60,18 @@ public class Join implements Serializable {
public void addProperty(Property prop) {
properties.add(prop);
declaredProperties.add(prop);
prop.setPersistentClass( getPersistentClass() );
}
public void addMappedsuperclassProperty(Property prop) {
properties.add(prop);
prop.setPersistentClass( getPersistentClass() );
}
public Iterator getDeclaredPropertyIterator() {
return declaredProperties.iterator();
}
public boolean containsProperty(Property prop) {
return properties.contains(prop);
}

View File

@ -0,0 +1,67 @@
package org.hibernate.mapping;
import java.util.*;
import java.util.List;
/**
* Represents a @MappedSuperclass.
* A @MappedSuperclass can be a superclass of an @Entity (root or not)
*
* This class primary goal is to give a representation to @MappedSuperclass
* in the metamodel in order to reflect them in the JPA 2 metamodel.
*
* Do not use outside this use case.
*
* A proper redesign will be evluated in Hibernate 4
*
* @author Emmanuel Bernard
*/
public class MappedSuperclass {
private final MappedSuperclass superMappedSuperclass;
private final PersistentClass superPersistentClass;
private final List properties;
public MappedSuperclass(MappedSuperclass superMappedSuperclass, PersistentClass superPersistentClass) {
this.superMappedSuperclass = superMappedSuperclass;
this.superPersistentClass = superPersistentClass;
this.properties = new ArrayList();
}
/**
* Returns the first superclass marked as @MappedSuperclass or null if:
* - none exists
* - or the first persistent superclass found is an @Entity
*
* @return the super MappedSuperclass
*/
public MappedSuperclass getSuperMappedSuperclass() {
return superMappedSuperclass;
}
/**
* Returns the PersistentClass of the first superclass marked as @Entity
* or null if none exists
*
* @return the PersistentClass of the superclass
*/
public PersistentClass getSuperPersistentClass() {
return superPersistentClass;
}
public Iterator getPropertyIterator() {
return properties.iterator();
}
public void addProperty(Property p) {
//Do not add duplicate properties
//TODO is it efficient enough?
String name = p.getName();
Iterator it = properties.iterator();
while (it.hasNext()) {
if ( name.equals( ((Property)it.next()).getName() ) ) {
return;
}
}
properties.add(p);
}
}

View File

@ -62,6 +62,7 @@ public abstract class PersistentClass implements Serializable, Filterable, MetaA
private String discriminatorValue;
private boolean lazy;
private ArrayList properties = new ArrayList();
private ArrayList declaredProperties = new ArrayList();
private final ArrayList subclasses = new ArrayList();
private final ArrayList subclassProperties = new ArrayList();
private final ArrayList subclassTables = new ArrayList();
@ -96,6 +97,7 @@ public abstract class PersistentClass implements Serializable, Filterable, MetaA
private java.util.Map tuplizerImpls;
protected int optimisticLockMode;
private MappedSuperclass superMappedSuperclass;
public String getClassName() {
return className;
@ -221,6 +223,7 @@ public abstract class PersistentClass implements Serializable, Filterable, MetaA
public void addProperty(Property p) {
properties.add(p);
declaredProperties.add(p);
p.setPersistentClass(this);
}
@ -811,4 +814,31 @@ public abstract class PersistentClass implements Serializable, Filterable, MetaA
}
public abstract boolean isLazyPropertiesCacheable();
// The following methods are added to support @MappedSuperclass in the metamodel
public Iterator getDeclaredPropertyIterator() {
ArrayList iterators = new ArrayList();
iterators.add( declaredProperties.iterator() );
for ( int i = 0; i < joins.size(); i++ ) {
Join join = ( Join ) joins.get( i );
iterators.add( join.getDeclaredPropertyIterator() );
}
return new JoinedIterator( iterators );
}
public void addMappedsuperclassProperty(Property p) {
properties.add(p);
p.setPersistentClass(this);
}
public MappedSuperclass getSuperMappedSuperclass() {
return superMappedSuperclass;
}
public void setSuperMappedSuperclass(MappedSuperclass superMappedSuperclass) {
this.superMappedSuperclass = superMappedSuperclass;
}
// End of @Mappedsuperclass support
}

View File

@ -93,6 +93,12 @@ public class Subclass extends PersistentClass {
super.addProperty(p);
getSuperclass().addSubclassProperty(p);
}
public void addMappedsuperClassProperty(Property p) {
super.addMappedsuperclassProperty( p );
getSuperclass().addSubclassProperty(p);
}
public void addJoin(Join j) {
super.addJoin(j);
getSuperclass().addSubclassJoin(j);