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:
parent
5cc638576f
commit
c7c6981a55
|
@ -66,6 +66,10 @@ public abstract class AbstractPropertyHolder implements PropertyHolder {
|
|||
return path;
|
||||
}
|
||||
|
||||
protected ExtendedMappings getMappings() {
|
||||
return mappings;
|
||||
}
|
||||
|
||||
/**
|
||||
* property can be null
|
||||
*/
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 ) ) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?" );
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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 );
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue