use of org.hibernate.metamodel.mapping.StateArrayContributorMetadata in project hibernate-orm by hibernate.
the class MappingModelCreationHelper method buildBasicAttributeMapping.
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Non-identifier attributes
@SuppressWarnings("rawtypes")
public static BasicAttributeMapping buildBasicAttributeMapping(String attrName, NavigableRole navigableRole, int stateArrayPosition, Property bootProperty, ManagedMappingType declaringType, BasicType attrType, String tableExpression, String attrColumnName, boolean isAttrFormula, String readExpr, String writeExpr, String columnDefinition, Long length, Integer precision, Integer scale, PropertyAccess propertyAccess, CascadeStyle cascadeStyle, MappingModelCreationProcess creationProcess) {
final Value value = bootProperty.getValue();
final BasicValue.Resolution<?> resolution = ((Resolvable) value).resolve();
final BasicValueConverter<?, ?> valueConverter = resolution.getValueConverter();
final StateArrayContributorMetadataAccess attributeMetadataAccess = entityMappingType -> new StateArrayContributorMetadata() {
private final MutabilityPlan mutabilityPlan = resolution.getMutabilityPlan();
private final boolean nullable = value.isNullable();
private final boolean insertable = bootProperty.isInsertable();
private final boolean updateable = bootProperty.isUpdateable();
private final boolean includeInOptimisticLocking = bootProperty.isOptimisticLocked();
@Override
public PropertyAccess getPropertyAccess() {
return propertyAccess;
}
@Override
public MutabilityPlan getMutabilityPlan() {
return mutabilityPlan;
}
@Override
public boolean isNullable() {
return nullable;
}
@Override
public boolean isInsertable() {
return insertable;
}
@Override
public boolean isUpdatable() {
return updateable;
}
@Override
public boolean isIncludedInDirtyChecking() {
// todo (6.0) : do not believe this is correct
return updateable;
}
@Override
public boolean isIncludedInOptimisticLocking() {
return includeInOptimisticLocking;
}
@Override
public CascadeStyle getCascadeStyle() {
return cascadeStyle;
}
};
final FetchTiming fetchTiming;
final FetchStyle fetchStyle;
if (declaringType instanceof EmbeddableMappingType) {
if (bootProperty.isLazy()) {
LOGGER.debugf("Attribute was declared lazy, but is part of an embeddable - `%s#%s` - LAZY will be ignored", declaringType.getNavigableRole().getFullPath(), bootProperty.getName());
}
fetchTiming = FetchTiming.IMMEDIATE;
fetchStyle = FetchStyle.JOIN;
} else {
fetchTiming = bootProperty.isLazy() ? FetchTiming.DELAYED : FetchTiming.IMMEDIATE;
fetchStyle = bootProperty.isLazy() ? FetchStyle.SELECT : FetchStyle.JOIN;
}
final ValueGeneration valueGeneration = bootProperty.getValueGenerationStrategy();
if (valueConverter != null) {
// we want to "decompose" the "type" into its various pieces as expected by the mapping
assert valueConverter.getRelationalJavaType() == resolution.getRelationalJavaType();
final BasicType<?> mappingBasicType = creationProcess.getCreationContext().getDomainModel().getTypeConfiguration().getBasicTypeRegistry().resolve(valueConverter.getRelationalJavaType(), resolution.getJdbcType());
return new BasicAttributeMapping(attrName, navigableRole, stateArrayPosition, attributeMetadataAccess, fetchTiming, fetchStyle, tableExpression, attrColumnName, isAttrFormula, null, null, columnDefinition, length, precision, scale, valueConverter, mappingBasicType.getJdbcMapping(), declaringType, propertyAccess, valueGeneration);
} else {
return new BasicAttributeMapping(attrName, navigableRole, stateArrayPosition, attributeMetadataAccess, fetchTiming, fetchStyle, tableExpression, attrColumnName, isAttrFormula, readExpr, writeExpr, columnDefinition, length, precision, scale, null, attrType, declaringType, propertyAccess, valueGeneration);
}
}
use of org.hibernate.metamodel.mapping.StateArrayContributorMetadata in project hibernate-orm by hibernate.
the class AbstractCompositeIdAndNaturalIdTest method testNaturalIdNullability.
@Test
@TestForIssue(jiraKey = "HHH-10360")
public void testNaturalIdNullability(SessionFactoryScope scope) {
final EntityMappingType accountMapping = scope.getSessionFactory().getRuntimeMetamodels().getEntityMappingType(Account.class);
final SingularAttributeMapping shortCodeMapping = ((SimpleNaturalIdMapping) accountMapping.getNaturalIdMapping()).getAttribute();
final StateArrayContributorMetadata shortCodeMetadata = shortCodeMapping.getAttributeMetadataAccess().resolveAttributeMetadata(null);
assertThat(shortCodeMetadata.isNullable(), is(false));
final EntityPersister rootEntityPersister = accountMapping.getRootEntityDescriptor().getEntityPersister();
final int shortCodeLegacyPropertyIndex = rootEntityPersister.getEntityMetamodel().getPropertyIndex("shortCode");
assertThat(shortCodeLegacyPropertyIndex, is(0));
assertThat(rootEntityPersister.getPropertyNullability()[shortCodeLegacyPropertyIndex], is(false));
}
use of org.hibernate.metamodel.mapping.StateArrayContributorMetadata in project hibernate-orm by hibernate.
the class ImmutableManyToOneNaturalIdAnnotationTest method testNaturalIdNullability.
@Test
@TestForIssue(jiraKey = "HHH-10360")
public void testNaturalIdNullability(SessionFactoryScope scope) {
// nullability is not specified for either properties making up
// the natural ID, so they should be nullable by annotation-specific default
final RuntimeMetamodels runtimeMetamodels = scope.getSessionFactory().getRuntimeMetamodels();
final EntityMappingType childMapping = runtimeMetamodels.getEntityMappingType(Child.class.getName());
final EntityPersister persister = childMapping.getEntityPersister();
final EntityMetamodel entityMetamodel = persister.getEntityMetamodel();
final int nameIndex = entityMetamodel.getPropertyIndex("name");
final int parentIndex = entityMetamodel.getPropertyIndex("parent");
// checking alphabetic sort in relation to EntityPersister/EntityMetamodel
assertThat(nameIndex, lessThan(parentIndex));
assertFalse(persister.getPropertyUpdateability()[nameIndex]);
assertFalse(persister.getPropertyUpdateability()[parentIndex]);
assertTrue(persister.getPropertyNullability()[nameIndex]);
assertTrue(persister.getPropertyNullability()[parentIndex]);
final NaturalIdMapping naturalIdMapping = childMapping.getNaturalIdMapping();
assertNotNull(naturalIdMapping);
assertThat(naturalIdMapping.getNaturalIdAttributes().size(), is(2));
// access by list-index should again be alphabetically sorted
final SingularAttributeMapping first = naturalIdMapping.getNaturalIdAttributes().get(0);
assertThat(first.getAttributeName(), is("name"));
final StateArrayContributorMetadata firstMetadata = first.getAttributeMetadataAccess().resolveAttributeMetadata(null);
assertFalse(firstMetadata.getMutabilityPlan().isMutable());
final SingularAttributeMapping second = naturalIdMapping.getNaturalIdAttributes().get(1);
assertThat(second.getAttributeName(), is("parent"));
final StateArrayContributorMetadata secondMetadata = second.getAttributeMetadataAccess().resolveAttributeMetadata(null);
assertFalse(secondMetadata.getMutabilityPlan().isMutable());
}
use of org.hibernate.metamodel.mapping.StateArrayContributorMetadata in project hibernate-orm by hibernate.
the class MappingModelCreationHelper method buildPluralAttributeMapping.
@SuppressWarnings("rawtypes")
public static PluralAttributeMapping buildPluralAttributeMapping(String attrName, int stateArrayPosition, Property bootProperty, ManagedMappingType declaringType, PropertyAccess propertyAccess, CascadeStyle cascadeStyle, FetchMode fetchMode, MappingModelCreationProcess creationProcess) {
final Collection bootValueMapping = (Collection) bootProperty.getValue();
final RuntimeModelCreationContext creationContext = creationProcess.getCreationContext();
final SessionFactoryImplementor sessionFactory = creationContext.getSessionFactory();
final SqlStringGenerationContext sqlStringGenerationContext = sessionFactory.getSqlStringGenerationContext();
final Dialect dialect = sqlStringGenerationContext.getDialect();
final MappingMetamodel domainModel = creationContext.getDomainModel();
final CollectionPersister collectionDescriptor = domainModel.findCollectionDescriptor(bootValueMapping.getRole());
assert collectionDescriptor != null;
final String tableExpression = ((Joinable) collectionDescriptor).getTableName();
final String sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName(bootProperty.getName());
final CollectionMappingType<?> collectionMappingType;
final JavaTypeRegistry jtdRegistry = creationContext.getJavaTypeRegistry();
final CollectionPart elementDescriptor = interpretElement(bootValueMapping, tableExpression, collectionDescriptor, sqlAliasStem, dialect, creationProcess);
final CollectionPart indexDescriptor;
CollectionIdentifierDescriptor identifierDescriptor = null;
final CollectionSemantics<?, ?> collectionSemantics = collectionDescriptor.getCollectionSemantics();
switch(collectionSemantics.getCollectionClassification()) {
case ARRAY:
{
collectionMappingType = new CollectionMappingTypeImpl(jtdRegistry.getDescriptor(Object[].class), StandardArraySemantics.INSTANCE);
final BasicValue index = (BasicValue) ((IndexedCollection) bootValueMapping).getIndex();
final SelectableMapping selectableMapping = SelectableMappingImpl.from(tableExpression, index.getSelectables().get(0), creationContext.getTypeConfiguration().getBasicTypeForJavaType(Integer.class), dialect, creationProcess.getSqmFunctionRegistry());
indexDescriptor = new BasicValuedCollectionPart(collectionDescriptor, CollectionPart.Nature.INDEX, // no converter
null, selectableMapping);
break;
}
case BAG:
{
collectionMappingType = new CollectionMappingTypeImpl(jtdRegistry.getDescriptor(java.util.Collection.class), StandardBagSemantics.INSTANCE);
indexDescriptor = null;
break;
}
case ID_BAG:
{
collectionMappingType = new CollectionMappingTypeImpl(jtdRegistry.getDescriptor(java.util.Collection.class), StandardIdentifierBagSemantics.INSTANCE);
indexDescriptor = null;
assert collectionDescriptor instanceof SQLLoadableCollection;
final SQLLoadableCollection loadableCollection = (SQLLoadableCollection) collectionDescriptor;
final String identifierColumnName = loadableCollection.getIdentifierColumnName();
assert identifierColumnName != null;
identifierDescriptor = new CollectionIdentifierDescriptorImpl(collectionDescriptor, tableExpression, identifierColumnName, (BasicType) loadableCollection.getIdentifierType());
break;
}
case LIST:
{
final BasicValue index = (BasicValue) ((IndexedCollection) bootValueMapping).getIndex();
final SelectableMapping selectableMapping = SelectableMappingImpl.from(tableExpression, index.getSelectables().get(0), creationContext.getTypeConfiguration().getBasicTypeForJavaType(Integer.class), dialect, creationProcess.getSqmFunctionRegistry());
indexDescriptor = new BasicValuedCollectionPart(collectionDescriptor, CollectionPart.Nature.INDEX, // no converter
null, selectableMapping);
collectionMappingType = new CollectionMappingTypeImpl(jtdRegistry.getDescriptor(List.class), StandardListSemantics.INSTANCE);
break;
}
case MAP:
case ORDERED_MAP:
case SORTED_MAP:
{
final Class<? extends java.util.Map> mapJavaType = collectionSemantics.getCollectionClassification() == CollectionClassification.SORTED_MAP ? SortedMap.class : java.util.Map.class;
collectionMappingType = new CollectionMappingTypeImpl(jtdRegistry.getDescriptor(mapJavaType), collectionSemantics);
final String mapKeyTableExpression;
if (bootValueMapping instanceof Map && ((Map) bootValueMapping).getMapKeyPropertyName() != null) {
mapKeyTableExpression = getTableIdentifierExpression(((Map) bootValueMapping).getIndex().getTable(), creationProcess);
} else {
mapKeyTableExpression = tableExpression;
}
indexDescriptor = interpretMapKey(bootValueMapping, collectionDescriptor, mapKeyTableExpression, sqlAliasStem, dialect, creationProcess);
break;
}
case SET:
case ORDERED_SET:
case SORTED_SET:
{
final Class<? extends java.util.Set> setJavaType = collectionSemantics.getCollectionClassification() == CollectionClassification.SORTED_MAP ? SortedSet.class : java.util.Set.class;
collectionMappingType = new CollectionMappingTypeImpl(jtdRegistry.getDescriptor(setJavaType), collectionSemantics);
indexDescriptor = null;
break;
}
default:
{
throw new MappingException("Unexpected CollectionClassification : " + collectionSemantics.getCollectionClassification());
}
}
final StateArrayContributorMetadata contributorMetadata = new StateArrayContributorMetadata() {
@Override
public PropertyAccess getPropertyAccess() {
return propertyAccess;
}
@Override
public MutabilityPlan getMutabilityPlan() {
return ImmutableMutabilityPlan.instance();
}
@Override
public boolean isNullable() {
return bootProperty.isOptional();
}
@Override
public boolean isInsertable() {
return bootProperty.isInsertable();
}
@Override
public boolean isUpdatable() {
return bootProperty.isUpdateable();
}
@Override
public boolean isIncludedInDirtyChecking() {
return false;
}
@Override
public boolean isIncludedInOptimisticLocking() {
return bootProperty.isOptimisticLocked();
}
@Override
public CascadeStyle getCascadeStyle() {
return cascadeStyle;
}
};
final FetchStyle style = FetchOptionsHelper.determineFetchStyleByMetadata(fetchMode, collectionDescriptor.getCollectionType(), sessionFactory);
final FetchTiming timing = FetchOptionsHelper.determineFetchTiming(style, collectionDescriptor.getCollectionType(), collectionDescriptor.isLazy(), collectionDescriptor.getRole(), sessionFactory);
final PluralAttributeMappingImpl pluralAttributeMapping = new PluralAttributeMappingImpl(attrName, bootValueMapping, propertyAccess, entityMappingType -> contributorMetadata, collectionMappingType, stateArrayPosition, elementDescriptor, indexDescriptor, identifierDescriptor, timing, style, cascadeStyle, declaringType, collectionDescriptor);
creationProcess.registerInitializationCallback("PluralAttributeMapping(" + bootValueMapping.getRole() + ")#finishInitialization", () -> {
pluralAttributeMapping.finishInitialization(bootProperty, bootValueMapping, creationProcess);
return true;
});
creationProcess.registerInitializationCallback("PluralAttributeMapping(" + bootValueMapping.getRole() + ") - key descriptor", () -> {
interpretPluralAttributeMappingKeyDescriptor(pluralAttributeMapping, bootValueMapping, collectionDescriptor, declaringType, dialect, creationProcess);
return true;
});
return pluralAttributeMapping;
}
use of org.hibernate.metamodel.mapping.StateArrayContributorMetadata in project hibernate-orm by hibernate.
the class EmbeddableMappingTypeImpl method finishInitialization.
private boolean finishInitialization(Component bootDescriptor, CompositeType compositeType, String rootTableExpression, String[] rootTableKeyColumnNames, MappingModelCreationProcess creationProcess) {
// for some reason I cannot get this to work, though only a single test fails - `CompositeElementTest`
// return finishInitialization(
// getNavigableRole(),
// bootDescriptor,
// compositeType,
// rootTableExpression,
// rootTableKeyColumnNames,
// this,
// representationStrategy,
// (name, type) -> {},
// (column, jdbcEnvironment) -> getTableIdentifierExpression(
// column.getValue().getTable(),
// jdbcEnvironment
// ),
// this::addAttribute,
// () -> {
// // We need the attribute mapping types to finish initialization first before we can build the column mappings
// creationProcess.registerInitializationCallback(
// "EmbeddableMappingType(" + getEmbeddedValueMapping().getNavigableRole().getFullPath() + ")#initColumnMappings",
// this::initColumnMappings
// );
// },
// creationProcess
// );
// todo (6.0) - get this ^^ to work, or drop the comment
final SessionFactoryImplementor sessionFactory = creationProcess.getCreationContext().getSessionFactory();
final TypeConfiguration typeConfiguration = sessionFactory.getTypeConfiguration();
final JdbcServices jdbcServices = sessionFactory.getJdbcServices();
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
final Dialect dialect = jdbcEnvironment.getDialect();
final String baseTableExpression = valueMapping.getContainingTableExpression();
final Type[] subtypes = compositeType.getSubtypes();
int attributeIndex = 0;
int columnPosition = 0;
// Reset the attribute mappings that were added in previous attempts
this.attributeMappings.clear();
for (Property bootPropertyDescriptor : bootDescriptor.getProperties()) {
final AttributeMapping attributeMapping;
final Type subtype = subtypes[attributeIndex];
if (subtype instanceof BasicType) {
final BasicValue basicValue = (BasicValue) bootPropertyDescriptor.getValue();
final Selectable selectable = basicValue.getColumn();
final String containingTableExpression;
final String columnExpression;
if (rootTableKeyColumnNames == null) {
if (selectable.isFormula()) {
columnExpression = selectable.getTemplate(dialect, creationProcess.getSqmFunctionRegistry());
} else {
columnExpression = selectable.getText(dialect);
}
if (selectable instanceof Column) {
containingTableExpression = MappingModelCreationHelper.getTableIdentifierExpression(((Column) selectable).getValue().getTable(), creationProcess);
} else {
containingTableExpression = baseTableExpression;
}
} else {
containingTableExpression = rootTableExpression;
columnExpression = rootTableKeyColumnNames[columnPosition];
}
final String columnDefinition;
final Long length;
final Integer precision;
final Integer scale;
if (selectable instanceof Column) {
Column column = (Column) selectable;
columnDefinition = column.getSqlType();
length = column.getLength();
precision = column.getPrecision();
scale = column.getScale();
} else {
columnDefinition = null;
length = null;
precision = null;
scale = null;
}
attributeMapping = MappingModelCreationHelper.buildBasicAttributeMapping(bootPropertyDescriptor.getName(), valueMapping.getNavigableRole().append(bootPropertyDescriptor.getName()), attributeIndex, bootPropertyDescriptor, this, (BasicType<?>) subtype, containingTableExpression, columnExpression, selectable.isFormula(), selectable.getCustomReadExpression(), selectable.getCustomWriteExpression(), columnDefinition, length, precision, scale, representationStrategy.resolvePropertyAccess(bootPropertyDescriptor), compositeType.getCascadeStyle(attributeIndex), creationProcess);
columnPosition++;
} else if (subtype instanceof AnyType) {
final Any bootValueMapping = (Any) bootPropertyDescriptor.getValue();
final AnyType anyType = (AnyType) subtype;
final PropertyAccess propertyAccess = representationStrategy.resolvePropertyAccess(bootPropertyDescriptor);
final boolean nullable = bootValueMapping.isNullable();
final boolean insertable = bootPropertyDescriptor.isInsertable();
final boolean updateable = bootPropertyDescriptor.isUpdateable();
final boolean includeInOptimisticLocking = bootPropertyDescriptor.isOptimisticLocked();
final CascadeStyle cascadeStyle = compositeType.getCascadeStyle(attributeIndex);
final MutabilityPlan<?> mutabilityPlan;
if (updateable) {
mutabilityPlan = new MutabilityPlan<Object>() {
@Override
public boolean isMutable() {
return true;
}
@Override
public Object deepCopy(Object value) {
if (value == null) {
return null;
}
return anyType.deepCopy(value, creationProcess.getCreationContext().getSessionFactory());
}
@Override
public Serializable disassemble(Object value, SharedSessionContract session) {
throw new NotYetImplementedFor6Exception(getClass());
}
@Override
public Object assemble(Serializable cached, SharedSessionContract session) {
throw new NotYetImplementedFor6Exception(getClass());
}
};
} else {
mutabilityPlan = ImmutableMutabilityPlan.INSTANCE;
}
final StateArrayContributorMetadataAccess attributeMetadataAccess = entityMappingType -> new StateArrayContributorMetadata() {
@Override
public PropertyAccess getPropertyAccess() {
return propertyAccess;
}
@Override
public MutabilityPlan<?> getMutabilityPlan() {
return mutabilityPlan;
}
@Override
public boolean isNullable() {
return nullable;
}
@Override
public boolean isInsertable() {
return insertable;
}
@Override
public boolean isUpdatable() {
return updateable;
}
@Override
public boolean isIncludedInDirtyChecking() {
// todo (6.0) : do not believe this is correct
return updateable;
}
@Override
public boolean isIncludedInOptimisticLocking() {
return includeInOptimisticLocking;
}
@Override
public CascadeStyle getCascadeStyle() {
return cascadeStyle;
}
};
attributeMapping = new DiscriminatedAssociationAttributeMapping(valueMapping.getNavigableRole().append(bootPropertyDescriptor.getName()), typeConfiguration.getJavaTypeRegistry().getDescriptor(Object.class), this, attributeIndex, attributeMetadataAccess, bootPropertyDescriptor.isLazy() ? FetchTiming.DELAYED : FetchTiming.IMMEDIATE, propertyAccess, bootPropertyDescriptor, anyType, bootValueMapping, creationProcess);
} else if (subtype instanceof CompositeType) {
final CompositeType subCompositeType = (CompositeType) subtype;
final int columnSpan = subCompositeType.getColumnSpan(sessionFactory);
final String subTableExpression;
final String[] subRootTableKeyColumnNames;
if (rootTableKeyColumnNames == null) {
subTableExpression = baseTableExpression;
subRootTableKeyColumnNames = null;
} else {
subTableExpression = rootTableExpression;
subRootTableKeyColumnNames = new String[columnSpan];
System.arraycopy(rootTableKeyColumnNames, columnPosition, subRootTableKeyColumnNames, 0, columnSpan);
}
attributeMapping = MappingModelCreationHelper.buildEmbeddedAttributeMapping(bootPropertyDescriptor.getName(), attributeIndex, bootPropertyDescriptor, this, subCompositeType, subTableExpression, subRootTableKeyColumnNames, representationStrategy.resolvePropertyAccess(bootPropertyDescriptor), compositeType.getCascadeStyle(attributeIndex), creationProcess);
columnPosition += columnSpan;
} else if (subtype instanceof CollectionType) {
final EntityPersister entityPersister = creationProcess.getEntityPersister(bootDescriptor.getOwner().getEntityName());
attributeMapping = MappingModelCreationHelper.buildPluralAttributeMapping(bootPropertyDescriptor.getName(), attributeIndex, bootPropertyDescriptor, entityPersister, representationStrategy.resolvePropertyAccess(bootPropertyDescriptor), compositeType.getCascadeStyle(attributeIndex), compositeType.getFetchMode(attributeIndex), creationProcess);
} else if (subtype instanceof EntityType) {
final EntityPersister entityPersister = creationProcess.getEntityPersister(bootDescriptor.getOwner().getEntityName());
attributeMapping = MappingModelCreationHelper.buildSingularAssociationAttributeMapping(bootPropertyDescriptor.getName(), valueMapping.getNavigableRole().append(bootPropertyDescriptor.getName()), attributeIndex, bootPropertyDescriptor, entityPersister, entityPersister, (EntityType) subtype, getRepresentationStrategy().resolvePropertyAccess(bootPropertyDescriptor), compositeType.getCascadeStyle(attributeIndex), creationProcess);
columnPosition += bootPropertyDescriptor.getColumnSpan();
} else {
throw new MappingException(String.format(Locale.ROOT, "Unable to determine attribute nature : %s#%s", bootDescriptor.getOwner().getEntityName(), bootPropertyDescriptor.getName()));
}
addAttribute(attributeMapping);
attributeIndex++;
}
// We need the attribute mapping types to finish initialization first before we can build the column mappings
creationProcess.registerInitializationCallback("EmbeddableMappingType(" + getEmbeddedValueMapping().getNavigableRole().getFullPath() + ")#initColumnMappings", this::initColumnMappings);
return true;
}
Aggregations