use of org.hibernate.cfg.InheritanceState in project hibernate-orm by hibernate.
the class MapBinder method bindKeyFromAssociationTable.
private void bindKeyFromAssociationTable(XClass collType, Map persistentClasses, String mapKeyPropertyName, XProperty property, boolean isEmbedded, MetadataBuildingContext buildingContext, Ejb3Column[] mapKeyColumns, Ejb3JoinColumn[] mapKeyManyToManyColumns, String targetPropertyName) {
if (mapKeyPropertyName != null) {
//this is an EJB3 @MapKey
PersistentClass associatedClass = (PersistentClass) persistentClasses.get(collType.getName());
if (associatedClass == null)
throw new AnnotationException("Associated class not found: " + collType);
Property mapProperty = BinderHelper.findPropertyByName(associatedClass, mapKeyPropertyName);
if (mapProperty == null) {
throw new AnnotationException("Map key property not found: " + collType + "." + mapKeyPropertyName);
}
org.hibernate.mapping.Map map = (org.hibernate.mapping.Map) this.collection;
// HHH-11005 - if InheritanceType.JOINED then need to find class defining the column
InheritanceState inheritanceState = inheritanceStatePerClass.get(collType);
PersistentClass targetPropertyPersistentClass = InheritanceType.JOINED.equals(inheritanceState.getType()) ? mapProperty.getPersistentClass() : associatedClass;
Value indexValue = createFormulatedValue(mapProperty.getValue(), map, targetPropertyName, associatedClass, targetPropertyPersistentClass, buildingContext);
map.setIndex(indexValue);
} else {
//this is a true Map mapping
//TODO ugly copy/pastle from CollectionBinder.bindManyToManySecondPass
String mapKeyType;
Class target = void.class;
/*
* target has priority over reflection for the map key type
* JPA 2 has priority
*/
if (property.isAnnotationPresent(MapKeyClass.class)) {
target = property.getAnnotation(MapKeyClass.class).value();
}
if (!void.class.equals(target)) {
mapKeyType = target.getName();
} else {
mapKeyType = property.getMapKey().getName();
}
PersistentClass collectionEntity = (PersistentClass) persistentClasses.get(mapKeyType);
boolean isIndexOfEntities = collectionEntity != null;
ManyToOne element = null;
org.hibernate.mapping.Map mapValue = (org.hibernate.mapping.Map) this.collection;
if (isIndexOfEntities) {
element = new ManyToOne(buildingContext.getMetadataCollector(), mapValue.getCollectionTable());
mapValue.setIndex(element);
element.setReferencedEntityName(mapKeyType);
//element.setFetchMode( fetchMode );
//element.setLazy( fetchMode != FetchMode.JOIN );
//make the second join non lazy
element.setFetchMode(FetchMode.JOIN);
element.setLazy(false);
//does not make sense for a map key element.setIgnoreNotFound( ignoreNotFound );
} else {
XClass keyXClass;
AnnotatedClassType classType;
if (BinderHelper.PRIMITIVE_NAMES.contains(mapKeyType)) {
classType = AnnotatedClassType.NONE;
keyXClass = null;
} else {
try {
keyXClass = buildingContext.getBuildingOptions().getReflectionManager().classForName(mapKeyType);
} catch (ClassLoadingException e) {
throw new AnnotationException("Unable to find class: " + mapKeyType, e);
}
classType = buildingContext.getMetadataCollector().getClassType(keyXClass);
// force in case of attribute override naming the key
if (isEmbedded || mappingDefinedAttributeOverrideOnMapKey(property)) {
classType = AnnotatedClassType.EMBEDDABLE;
}
}
CollectionPropertyHolder holder = PropertyHolderBuilder.buildPropertyHolder(mapValue, StringHelper.qualify(mapValue.getRole(), "mapkey"), keyXClass, property, propertyHolder, buildingContext);
// 'propertyHolder' is the PropertyHolder for the owner of the collection
// 'holder' is the CollectionPropertyHolder.
// 'property' is the collection XProperty
propertyHolder.startingProperty(property);
holder.prepare(property);
PersistentClass owner = mapValue.getOwner();
AccessType accessType;
// String accessType = access != null ? access.value() : null;
if (owner.getIdentifierProperty() != null) {
accessType = owner.getIdentifierProperty().getPropertyAccessorName().equals("property") ? AccessType.PROPERTY : AccessType.FIELD;
} else if (owner.getIdentifierMapper() != null && owner.getIdentifierMapper().getPropertySpan() > 0) {
Property prop = (Property) owner.getIdentifierMapper().getPropertyIterator().next();
accessType = prop.getPropertyAccessorName().equals("property") ? AccessType.PROPERTY : AccessType.FIELD;
} else {
throw new AssertionFailure("Unable to guess collection property accessor name");
}
if (AnnotatedClassType.EMBEDDABLE.equals(classType)) {
EntityBinder entityBinder = new EntityBinder();
PropertyData inferredData;
if (isHibernateExtensionMapping()) {
inferredData = new PropertyPreloadedData(AccessType.PROPERTY, "index", keyXClass);
} else {
//"key" is the JPA 2 prefix for map keys
inferredData = new PropertyPreloadedData(AccessType.PROPERTY, "key", keyXClass);
}
//TODO be smart with isNullable
Component component = AnnotationBinder.fillComponent(holder, inferredData, accessType, true, entityBinder, false, false, true, buildingContext, inheritanceStatePerClass);
mapValue.setIndex(component);
} else {
SimpleValueBinder elementBinder = new SimpleValueBinder();
elementBinder.setBuildingContext(buildingContext);
elementBinder.setReturnedClassName(mapKeyType);
Ejb3Column[] elementColumns = mapKeyColumns;
if (elementColumns == null || elementColumns.length == 0) {
elementColumns = new Ejb3Column[1];
Ejb3Column column = new Ejb3Column();
column.setImplicit(false);
column.setNullable(true);
column.setLength(Ejb3Column.DEFAULT_COLUMN_LENGTH);
column.setLogicalColumnName(Collection.DEFAULT_KEY_COLUMN_NAME);
//TODO create an EMPTY_JOINS collection
column.setJoins(new HashMap<String, Join>());
column.setBuildingContext(buildingContext);
column.bind();
elementColumns[0] = column;
}
//override the table
for (Ejb3Column column : elementColumns) {
column.setTable(mapValue.getCollectionTable());
}
elementBinder.setColumns(elementColumns);
//do not call setType as it extract the type from @Type
//the algorithm generally does not apply for map key anyway
elementBinder.setKey(true);
elementBinder.setType(property, keyXClass, this.collection.getOwnerEntityName(), holder.mapKeyAttributeConverterDescriptor(property, keyXClass));
elementBinder.setPersistentClassName(propertyHolder.getEntityName());
elementBinder.setAccessType(accessType);
mapValue.setIndex(elementBinder.make());
}
}
//FIXME pass the Index Entity JoinColumns
if (!collection.isOneToMany()) {
//index column shoud not be null
for (Ejb3JoinColumn col : mapKeyManyToManyColumns) {
col.forceNotNull();
}
}
if (element != null) {
final javax.persistence.ForeignKey foreignKey = getMapKeyForeignKey(property);
if (foreignKey != null) {
if (foreignKey.value() == ConstraintMode.NO_CONSTRAINT) {
element.setForeignKeyName("none");
} else {
element.setForeignKeyName(StringHelper.nullIfEmpty(foreignKey.name()));
element.setForeignKeyDefinition(StringHelper.nullIfEmpty(foreignKey.foreignKeyDefinition()));
}
}
}
if (isIndexOfEntities) {
bindManytoManyInverseFk(collectionEntity, mapKeyManyToManyColumns, element, //a map key column has no unique constraint
false, buildingContext);
}
}
}
use of org.hibernate.cfg.InheritanceState in project hibernate-orm by hibernate.
the class AnnotationMetadataSourceProcessorImpl method processEntityHierarchies.
@Override
public void processEntityHierarchies(Set<String> processedEntityNames) {
final List<XClass> orderedClasses = orderAndFillHierarchy(xClasses);
Map<XClass, InheritanceState> inheritanceStatePerClass = AnnotationBinder.buildInheritanceStates(orderedClasses, rootMetadataBuildingContext);
for (XClass clazz : orderedClasses) {
if (processedEntityNames.contains(clazz.getName())) {
log.debugf("Skipping annotated class processing of entity [%s], as it has already been processed", clazz);
continue;
}
AnnotationBinder.bindClass(clazz, inheritanceStatePerClass, rootMetadataBuildingContext);
processedEntityNames.add(clazz.getName());
}
}
Aggregations