use of jakarta.persistence.GeneratedValue in project hibernate-orm by hibernate.
the class AnnotationBinder method processId.
private static void processId(PropertyHolder propertyHolder, PropertyData inferredData, SimpleValue idValue, Map<String, IdentifierGeneratorDefinition> classGenerators, boolean isIdentifierMapper, MetadataBuildingContext buildingContext) {
if (isIdentifierMapper) {
throw new AnnotationException("@IdClass class should not have @Id nor @EmbeddedId properties: " + BinderHelper.getPath(propertyHolder, inferredData));
}
XClass entityXClass = inferredData.getClassOrElement();
XProperty idXProperty = inferredData.getProperty();
final Annotation generatorAnnotation = HCANNHelper.findContainingAnnotation(idXProperty, IdGeneratorType.class);
if (generatorAnnotation != null) {
idValue.setCustomIdGeneratorCreator(new CustomIdGeneratorCreator(generatorAnnotation, idXProperty));
} else {
// manage composite related metadata
// guess if its a component and find id data access (property, field etc)
final boolean isComponent = entityXClass.isAnnotationPresent(Embeddable.class) || idXProperty.isAnnotationPresent(EmbeddedId.class);
GeneratedValue generatedValue = idXProperty.getAnnotation(GeneratedValue.class);
String generatorType = generatedValue != null ? generatorType(generatedValue, buildingContext, entityXClass) : "assigned";
String generatorName = generatedValue != null ? generatedValue.generator() : "";
if (isComponent) {
// a component must not have any generator
generatorType = "assigned";
}
if (isGlobalGeneratorNameGlobal(buildingContext)) {
buildGenerators(idXProperty, buildingContext);
SecondPass secondPass = new IdGeneratorResolverSecondPass(idValue, idXProperty, generatorType, generatorName, buildingContext);
buildingContext.getMetadataCollector().addSecondPass(secondPass);
} else {
// clone classGenerator and override with local values
HashMap<String, IdentifierGeneratorDefinition> localGenerators = new HashMap<>(classGenerators);
localGenerators.putAll(buildGenerators(idXProperty, buildingContext));
makeIdGenerator(idValue, idXProperty, generatorType, generatorName, buildingContext, localGenerators);
}
if (LOG.isTraceEnabled()) {
LOG.tracev("Bind {0} on {1}", (isComponent ? "@EmbeddedId" : "@Id"), inferredData.getPropertyName());
}
}
}
use of jakarta.persistence.GeneratedValue 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, Class<? extends EmbeddableInstantiator> customInstantiatorImpl, Class<? extends CompositeUserType<?>> compositeUserTypeClass, 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, customInstantiatorImpl, buildingContext);
String subpath = BinderHelper.getPath(propertyHolder, inferredData);
LOG.tracev("Binding component with path: {0}", subpath);
PropertyHolder subHolder = 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<>();
final CompositeUserType<?> compositeUserType;
XClass returnedClassOrElement;
if (compositeUserTypeClass == null) {
compositeUserType = null;
returnedClassOrElement = inferredData.getClassOrElement();
} else {
compositeUserType = buildingContext.getBootstrapContext().getServiceRegistry().getService(ManagedBeanRegistry.class).getBean(compositeUserTypeClass).getBeanInstance();
comp.setTypeName(compositeUserTypeClass.getName());
returnedClassOrElement = buildingContext.getBootstrapContext().getReflectionManager().toXClass(compositeUserType.embeddable());
}
List<PropertyData> baseClassElements = null;
Map<String, PropertyData> orderedBaseClassElements = new HashMap<>();
XClass baseReturnedClassOrElement;
if (baseInferredData != null) {
baseClassElements = new ArrayList<>();
baseReturnedClassOrElement = baseInferredData.getClassOrElement();
// might be spread across the subclasses and super classes.
while (!Object.class.getName().equals(baseReturnedClassOrElement.getName())) {
addElementsOfClass(baseClassElements, new PropertyContainer(baseReturnedClassOrElement, xClassProcessed, propertyAccessor), buildingContext);
for (PropertyData element : baseClassElements) {
orderedBaseClassElements.put(element.getPropertyName(), element);
}
baseReturnedClassOrElement = baseReturnedClassOrElement.getSuperclass();
}
}
// embeddable elements can have type defs
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 type variables 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 = hasToOneAnnotation(entityPropertyData.getProperty());
final boolean isOfDifferentType = !entityPropertyData.getClassOrElement().equals(idClassPropertyData.getClassOrElement());
if (!hasXToOneAnnotation || !isOfDifferentType) {
// this works since they are in the same order
classElements.set(i, entityPropertyData);
}
// else {
// 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);
}
}
}
}
for (PropertyData propertyAnnotatedElement : classElements) {
processElementAnnotations(subHolder, isNullable ? Nullability.NO_CONSTRAINT : Nullability.FORCED_NOT_NULL, propertyAnnotatedElement, new HashMap<>(), entityBinder, isIdentifierMapper, isComponentEmbedded, inSecondPass, buildingContext, inheritanceStatePerClass);
XProperty property = propertyAnnotatedElement.getProperty();
if (property.isAnnotationPresent(GeneratedValue.class) && property.isAnnotationPresent(Id.class)) {
GeneratedValue generatedValue = property.getAnnotation(GeneratedValue.class);
String generatorType = generatedValue != null ? generatorType(generatedValue, buildingContext, property.getType()) : DEFAULT_ID_GEN_STRATEGY;
String generator = generatedValue != null ? generatedValue.generator() : "";
if (isGlobalGeneratorNameGlobal(buildingContext)) {
buildGenerators(property, buildingContext);
SecondPass secondPass = new IdGeneratorResolverSecondPass((SimpleValue) comp.getProperty(property.getName()).getValue(), property, generatorType, generator, buildingContext);
buildingContext.getMetadataCollector().addSecondPass(secondPass);
handleTypeDescriptorRegistrations(property, buildingContext);
bindEmbeddableInstantiatorRegistrations(property, buildingContext);
bindCompositeUserTypeRegistrations(property, buildingContext);
} else {
Map<String, IdentifierGeneratorDefinition> localGenerators = new HashMap<>(buildGenerators(property, buildingContext));
makeIdGenerator((SimpleValue) comp.getProperty(property.getName()).getValue(), property, generatorType, generator, buildingContext, localGenerators);
}
}
}
if (compositeUserType != null) {
comp.sortProperties();
final List<String> sortedPropertyNames = new ArrayList<>(comp.getPropertySpan());
final List<Type> sortedPropertyTypes = new ArrayList<>(comp.getPropertySpan());
final PropertyAccessStrategy strategy = new PropertyAccessStrategyCompositeUserTypeImpl(compositeUserType, sortedPropertyNames, sortedPropertyTypes);
for (Property property : comp.getProperties()) {
sortedPropertyNames.add(property.getName());
sortedPropertyTypes.add(PropertyAccessStrategyMixedImpl.INSTANCE.buildPropertyAccess(compositeUserType.embeddable(), property.getName(), false).getGetter().getReturnType());
property.setPropertyAccessStrategy(strategy);
}
}
return comp;
}
use of jakarta.persistence.GeneratedValue in project hibernate-orm by hibernate.
the class BinderHelper method getIdentifierGenerator.
private static IdentifierGeneratorDefinition getIdentifierGenerator(String name, XProperty idXProperty, Map<String, IdentifierGeneratorDefinition> localGenerators, MetadataBuildingContext buildingContext) {
if (localGenerators != null) {
final IdentifierGeneratorDefinition result = localGenerators.get(name);
if (result != null) {
return result;
}
}
final IdentifierGeneratorDefinition globalDefinition = buildingContext.getMetadataCollector().getIdentifierGenerator(name);
if (globalDefinition != null) {
return globalDefinition;
}
log.debugf("Could not resolve explicit IdentifierGeneratorDefinition - using implicit interpretation (%s)", name);
// If we were unable to locate an actual matching named generator assume a sequence/table of the given name.
// this really needs access to the `jakarta.persistence.GenerationType` to work completely properly
//
// (the crux of HHH-12122)
// temporarily, in lieu of having access to GenerationType, assume the EnhancedSequenceGenerator
// for the purpose of testing the feasibility of the approach
final GeneratedValue generatedValueAnn = idXProperty.getAnnotation(GeneratedValue.class);
if (generatedValueAnn == null) {
// this should really never happen, but its easy to protect against it...
return new IdentifierGeneratorDefinition("assigned", "assigned");
}
final IdGeneratorStrategyInterpreter generationInterpreter = buildingContext.getBuildingOptions().getIdGenerationTypeInterpreter();
final GenerationType generationType = interpretGenerationType(generatedValueAnn);
if (generationType == null || generationType == GenerationType.SEQUENCE) {
// NOTE : `null` will ultimately be interpreted as "hibernate_sequence"
log.debugf("Building implicit sequence-based IdentifierGeneratorDefinition (%s)", name);
final IdentifierGeneratorDefinition.Builder builder = new IdentifierGeneratorDefinition.Builder();
generationInterpreter.interpretSequenceGenerator(new SequenceGenerator() {
@Override
public String name() {
return name;
}
@Override
public String sequenceName() {
return "";
}
@Override
public String catalog() {
return "";
}
@Override
public String schema() {
return "";
}
@Override
public int initialValue() {
return 1;
}
@Override
public int allocationSize() {
return 50;
}
@Override
public Class<? extends Annotation> annotationType() {
return SequenceGenerator.class;
}
}, builder);
return builder.build();
} else if (generationType == GenerationType.TABLE) {
// NOTE : `null` will ultimately be interpreted as "hibernate_sequence"
log.debugf("Building implicit table-based IdentifierGeneratorDefinition (%s)", name);
final IdentifierGeneratorDefinition.Builder builder = new IdentifierGeneratorDefinition.Builder();
generationInterpreter.interpretTableGenerator(new TableGenerator() {
@Override
public String name() {
return name;
}
@Override
public String table() {
return "";
}
@Override
public int initialValue() {
return 0;
}
@Override
public int allocationSize() {
return 50;
}
@Override
public String catalog() {
return "";
}
@Override
public String schema() {
return "";
}
@Override
public String pkColumnName() {
return "";
}
@Override
public String valueColumnName() {
return "";
}
@Override
public String pkColumnValue() {
return "";
}
@Override
public UniqueConstraint[] uniqueConstraints() {
return new UniqueConstraint[0];
}
@Override
public Index[] indexes() {
return new Index[0];
}
@Override
public Class<? extends Annotation> annotationType() {
return TableGenerator.class;
}
}, builder);
return builder.build();
}
// really AUTO and IDENTITY work the same in this respect, aside from the actual strategy name
final String strategyName;
if (generationType == GenerationType.IDENTITY) {
strategyName = "identity";
} else {
strategyName = generationInterpreter.determineGeneratorName(generationType, new GeneratorNameDeterminationContext() {
@Override
public Class<?> getIdType() {
return buildingContext.getBootstrapContext().getReflectionManager().toClass(idXProperty.getType());
}
@Override
public String getGeneratedValueGeneratorName() {
return generatedValueAnn.generator();
}
});
}
log.debugf("Building implicit generic IdentifierGeneratorDefinition (%s) : %s", name, strategyName);
return new IdentifierGeneratorDefinition(name, strategyName, Collections.singletonMap(IdentifierGenerator.GENERATOR_NAME, name));
}
Aggregations