use of org.hibernate.mapping.Component in project hibernate-orm by hibernate.
the class AnnotationBinder method mapAsIdClass.
private static boolean mapAsIdClass(Map<XClass, InheritanceState> inheritanceStatePerClass, InheritanceState inheritanceState, PersistentClass persistentClass, EntityBinder entityBinder, PropertyHolder propertyHolder, InheritanceState.ElementsToProcess elementsToProcess, Set<String> idPropertiesIfIdClass, MetadataBuildingContext context) {
/*
* We are looking for @IdClass
* In general we map the id class as identifier using the mapping metadata of the main entity's properties
* and we create an identifier mapper containing the id properties of the main entity
*
* In JPA 2, there is a shortcut if the id class is the Pk of the associated class pointed to by the id
* it ought to be treated as an embedded and not a real IdClass (at least in the Hibernate's internal way
*/
XClass classWithIdClass = inheritanceState.getClassWithIdClass(false);
if (classWithIdClass != null) {
IdClass idClass = classWithIdClass.getAnnotation(IdClass.class);
XClass compositeClass = context.getBuildingOptions().getReflectionManager().toXClass(idClass.value());
PropertyData inferredData = new PropertyPreloadedData(entityBinder.getPropertyAccessType(), "id", compositeClass);
PropertyData baseInferredData = new PropertyPreloadedData(entityBinder.getPropertyAccessType(), "id", classWithIdClass);
AccessType propertyAccessor = entityBinder.getPropertyAccessor(compositeClass);
//In JPA 2, there is a shortcut if the IdClass is the Pk of the associated class pointed to by the id
//it ought to be treated as an embedded and not a real IdClass (at least in the Hibernate's internal way
final boolean isFakeIdClass = isIdClassPkOfTheAssociatedEntity(elementsToProcess, compositeClass, inferredData, baseInferredData, propertyAccessor, inheritanceStatePerClass, context);
if (isFakeIdClass) {
return false;
}
boolean isComponent = true;
String generatorType = "assigned";
String generator = BinderHelper.ANNOTATION_STRING_DEFAULT;
boolean ignoreIdAnnotations = entityBinder.isIgnoreIdAnnotations();
entityBinder.setIgnoreIdAnnotations(true);
propertyHolder.setInIdClass(true);
bindIdClass(generatorType, generator, inferredData, baseInferredData, null, propertyHolder, isComponent, propertyAccessor, entityBinder, true, false, context, inheritanceStatePerClass);
propertyHolder.setInIdClass(null);
inferredData = new PropertyPreloadedData(propertyAccessor, PropertyPath.IDENTIFIER_MAPPER_PROPERTY, compositeClass);
Component mapper = fillComponent(propertyHolder, inferredData, baseInferredData, propertyAccessor, false, entityBinder, true, true, false, context, inheritanceStatePerClass);
entityBinder.setIgnoreIdAnnotations(ignoreIdAnnotations);
persistentClass.setIdentifierMapper(mapper);
//If id definition is on a mapped superclass, update the mapping
final org.hibernate.mapping.MappedSuperclass superclass = BinderHelper.getMappedSuperclassOrNull(classWithIdClass, inheritanceStatePerClass, context);
if (superclass != null) {
superclass.setDeclaredIdentifierMapper(mapper);
} else {
//we are for sure on the entity
persistentClass.setDeclaredIdentifierMapper(mapper);
}
Property property = new Property();
property.setName(PropertyPath.IDENTIFIER_MAPPER_PROPERTY);
property.setUpdateable(false);
property.setInsertable(false);
property.setValue(mapper);
property.setPropertyAccessorName("embedded");
persistentClass.addProperty(property);
entityBinder.setIgnoreIdAnnotations(true);
Iterator properties = mapper.getPropertyIterator();
while (properties.hasNext()) {
idPropertiesIfIdClass.add(((Property) properties.next()).getName());
}
return true;
} else {
return false;
}
}
use of org.hibernate.mapping.Component in project hibernate-orm by hibernate.
the class AnnotationBinder method fillComponent.
public static Component fillComponent(PropertyHolder propertyHolder, PropertyData inferredData, //base inferred data correspond to the entity reproducing inferredData's properties (ie IdClass)
PropertyData baseInferredData, AccessType propertyAccessor, boolean isNullable, EntityBinder entityBinder, boolean isComponentEmbedded, boolean isIdentifierMapper, boolean inSecondPass, MetadataBuildingContext buildingContext, Map<XClass, InheritanceState> inheritanceStatePerClass) {
/**
* inSecondPass can only be used to apply right away the second pass of a composite-element
* Because it's a value type, there is no bidirectional association, hence second pass
* ordering does not matter
*/
Component comp = createComponent(propertyHolder, inferredData, isComponentEmbedded, isIdentifierMapper, buildingContext);
String subpath = BinderHelper.getPath(propertyHolder, inferredData);
LOG.tracev("Binding component with path: {0}", subpath);
PropertyHolder subHolder = PropertyHolderBuilder.buildPropertyHolder(comp, subpath, inferredData, propertyHolder, buildingContext);
// propertyHolder here is the owner of the component property. Tell it we are about to start the component...
propertyHolder.startingProperty(inferredData.getProperty());
final XClass xClassProcessed = inferredData.getPropertyClass();
List<PropertyData> classElements = new ArrayList<PropertyData>();
XClass returnedClassOrElement = inferredData.getClassOrElement();
List<PropertyData> baseClassElements = null;
Map<String, PropertyData> orderedBaseClassElements = new HashMap<String, PropertyData>();
XClass baseReturnedClassOrElement;
if (baseInferredData != null) {
baseClassElements = new ArrayList<PropertyData>();
baseReturnedClassOrElement = baseInferredData.getClassOrElement();
bindTypeDefs(baseReturnedClassOrElement, buildingContext);
// might be spread across the subclasses and super classes.
while (!Object.class.getName().equals(baseReturnedClassOrElement.getName())) {
PropertyContainer propContainer = new PropertyContainer(baseReturnedClassOrElement, xClassProcessed, propertyAccessor);
addElementsOfClass(baseClassElements, propContainer, buildingContext);
for (PropertyData element : baseClassElements) {
orderedBaseClassElements.put(element.getPropertyName(), element);
}
baseReturnedClassOrElement = baseReturnedClassOrElement.getSuperclass();
}
}
//embeddable elements can have type defs
bindTypeDefs(returnedClassOrElement, buildingContext);
PropertyContainer propContainer = new PropertyContainer(returnedClassOrElement, xClassProcessed, propertyAccessor);
addElementsOfClass(classElements, propContainer, buildingContext);
//add elements of the embeddable superclass
XClass superClass = xClassProcessed.getSuperclass();
while (superClass != null && superClass.isAnnotationPresent(MappedSuperclass.class)) {
//FIXME: proper support of typevariables incl var resolved at upper levels
propContainer = new PropertyContainer(superClass, xClassProcessed, propertyAccessor);
addElementsOfClass(classElements, propContainer, buildingContext);
superClass = superClass.getSuperclass();
}
if (baseClassElements != null) {
//useful to avoid breaking pre JPA 2 mappings
if (!hasAnnotationsOnIdClass(xClassProcessed)) {
for (int i = 0; i < classElements.size(); i++) {
final PropertyData idClassPropertyData = classElements.get(i);
final PropertyData entityPropertyData = orderedBaseClassElements.get(idClassPropertyData.getPropertyName());
if (propertyHolder.isInIdClass()) {
if (entityPropertyData == null) {
throw new AnnotationException("Property of @IdClass not found in entity " + baseInferredData.getPropertyClass().getName() + ": " + idClassPropertyData.getPropertyName());
}
final boolean hasXToOneAnnotation = entityPropertyData.getProperty().isAnnotationPresent(ManyToOne.class) || entityPropertyData.getProperty().isAnnotationPresent(OneToOne.class);
final boolean isOfDifferentType = !entityPropertyData.getClassOrElement().equals(idClassPropertyData.getClassOrElement());
if (hasXToOneAnnotation && isOfDifferentType) {
//don't replace here as we need to use the actual original return type
//the annotation overriding will be dealt with by a mechanism similar to @MapsId
} else {
//this works since they are in the same order
classElements.set(i, entityPropertyData);
}
} else {
//this works since they are in the same order
classElements.set(i, entityPropertyData);
}
}
}
}
for (PropertyData propertyAnnotatedElement : classElements) {
processElementAnnotations(subHolder, isNullable ? Nullability.NO_CONSTRAINT : Nullability.FORCED_NOT_NULL, propertyAnnotatedElement, new HashMap<String, IdentifierGeneratorDefinition>(), entityBinder, isIdentifierMapper, isComponentEmbedded, inSecondPass, buildingContext, inheritanceStatePerClass);
XProperty property = propertyAnnotatedElement.getProperty();
if (property.isAnnotationPresent(GeneratedValue.class) && property.isAnnotationPresent(Id.class)) {
//clone classGenerator and override with local values
Map<String, IdentifierGeneratorDefinition> localGenerators = new HashMap<String, IdentifierGeneratorDefinition>();
localGenerators.putAll(buildLocalGenerators(property, buildingContext));
GeneratedValue generatedValue = property.getAnnotation(GeneratedValue.class);
String generatorType = generatedValue != null ? generatorType(generatedValue.strategy(), buildingContext, property.getType()) : "assigned";
String generator = generatedValue != null ? generatedValue.generator() : BinderHelper.ANNOTATION_STRING_DEFAULT;
BinderHelper.makeIdGenerator((SimpleValue) comp.getProperty(property.getName()).getValue(), generatorType, generator, buildingContext, localGenerators);
}
}
return comp;
}
Aggregations