use of org.hibernate.metamodel.mapping.StateArrayContributorMapping in project hibernate-orm by hibernate.
the class AbstractEntityPersister method selectFragment.
@Override
public String selectFragment(String alias, String suffix) {
final QuerySpec rootQuerySpec = new QuerySpec(true);
final String rootTableName = getRootTableName();
final LoaderSqlAstCreationState sqlAstCreationState = new LoaderSqlAstCreationState(rootQuerySpec, new SqlAliasBaseManager(), new SimpleFromClauseAccessImpl(), LockOptions.NONE, (fetchParent, querySpec, creationState) -> {
final List<Fetch> fetches = new ArrayList<>();
fetchParent.getReferencedMappingContainer().visitFetchables(fetchable -> {
// Ignore plural attributes
if (fetchable instanceof PluralAttributeMapping) {
return;
}
FetchTiming fetchTiming = fetchable.getMappedFetchOptions().getTiming();
final boolean selectable;
if (fetchable instanceof StateArrayContributorMapping) {
final int propertyNumber = ((StateArrayContributorMapping) fetchable).getStateArrayPosition();
final int tableNumber = getSubclassPropertyTableNumber(propertyNumber);
selectable = !isSubclassTableSequentialSelect(tableNumber) && propertySelectable[propertyNumber];
} else {
selectable = true;
}
if (fetchable instanceof BasicValuedModelPart) {
// Ignore lazy basic columns
if (fetchTiming == FetchTiming.DELAYED) {
return;
}
} else if (fetchable instanceof Association) {
final Association association = (Association) fetchable;
// Ignore the fetchable if the FK is on the other side
if (association.getSideNature() == ForeignKeyDescriptor.Nature.TARGET) {
return;
}
// Ensure the FK comes from the root table
if (!rootTableName.equals(association.getForeignKeyDescriptor().getKeyTable())) {
return;
}
fetchTiming = FetchTiming.DELAYED;
}
if (selectable) {
final NavigablePath navigablePath = fetchParent.resolveNavigablePath(fetchable);
final Fetch fetch = fetchParent.generateFetchableFetch(fetchable, navigablePath, fetchTiming, true, null, creationState);
fetches.add(fetch);
}
}, null);
return fetches;
}, true, getFactory());
final NavigablePath entityPath = new NavigablePath(getRootPathName());
final TableGroup rootTableGroup = createRootTableGroup(true, entityPath, null, () -> p -> {
}, new SqlAliasBaseConstant(alias), sqlAstCreationState.getSqlExpressionResolver(), sqlAstCreationState.getFromClauseAccess(), getFactory());
rootQuerySpec.getFromClause().addRoot(rootTableGroup);
sqlAstCreationState.getFromClauseAccess().registerTableGroup(entityPath, rootTableGroup);
createDomainResult(entityPath, rootTableGroup, null, sqlAstCreationState);
// Wrap expressions with aliases
final SelectClause selectClause = rootQuerySpec.getSelectClause();
final List<SqlSelection> sqlSelections = selectClause.getSqlSelections();
int i = 0;
for (String identifierAlias : identifierAliases) {
sqlSelections.set(i, new SqlSelectionImpl(i, i + 1, new AliasedExpression(sqlSelections.get(i).getExpression(), identifierAlias + suffix)));
i++;
}
if (entityMetamodel.hasSubclasses()) {
sqlSelections.set(i, new SqlSelectionImpl(i, i + 1, new AliasedExpression(sqlSelections.get(i).getExpression(), getDiscriminatorAlias() + suffix)));
i++;
}
if (hasRowId()) {
sqlSelections.set(i, new SqlSelectionImpl(i, i + 1, new AliasedExpression(sqlSelections.get(i).getExpression(), ROWID_ALIAS + suffix)));
i++;
}
final String[] columnAliases = getSubclassColumnAliasClosure();
final String[] formulaAliases = getSubclassFormulaAliasClosure();
int columnIndex = 0;
int formulaIndex = 0;
for (; i < sqlSelections.size(); i++) {
final SqlSelection sqlSelection = sqlSelections.get(i);
final ColumnReference columnReference = (ColumnReference) sqlSelection.getExpression();
final String selectAlias;
if (!columnReference.isColumnExpressionFormula()) {
// Skip over columns that are not selectable like in the fetch generation
while (!subclassColumnSelectableClosure[columnIndex]) {
columnIndex++;
}
selectAlias = columnAliases[columnIndex++] + suffix;
} else {
selectAlias = formulaAliases[formulaIndex++] + suffix;
}
sqlSelections.set(i, new SqlSelectionImpl(sqlSelection.getValuesArrayPosition(), sqlSelection.getJdbcResultSetIndex(), new AliasedExpression(sqlSelection.getExpression(), selectAlias)));
}
final String sql = getFactory().getJdbcServices().getDialect().getSqlAstTranslatorFactory().buildSelectTranslator(getFactory(), new SelectStatement(rootQuerySpec)).translate(null, QueryOptions.NONE).getSql();
final int fromIndex = sql.lastIndexOf(" from");
final String expression;
if (fromIndex != -1) {
expression = sql.substring("select ".length(), fromIndex);
} else {
expression = sql.substring("select ".length());
}
return expression;
}
use of org.hibernate.metamodel.mapping.StateArrayContributorMapping in project hibernate-orm by hibernate.
the class AbstractEntityPersister method resolveDirtyAttributeIndexes.
@Override
public int[] resolveDirtyAttributeIndexes(final Object[] currentState, final Object[] previousState, final String[] attributeNames, final SessionImplementor session) {
final BitSet mutablePropertiesIndexes = entityMetamodel.getMutablePropertiesIndexes();
final int estimatedSize = attributeNames == null ? 0 : attributeNames.length + mutablePropertiesIndexes.cardinality();
final List<Integer> fields = new ArrayList<>(estimatedSize);
if (estimatedSize == 0) {
return ArrayHelper.EMPTY_INT_ARRAY;
}
if (!mutablePropertiesIndexes.isEmpty()) {
// We have to check the state for "mutable" properties as dirty tracking isn't aware of mutable types
final Type[] propertyTypes = entityMetamodel.getPropertyTypes();
final boolean[] propertyCheckability = entityMetamodel.getPropertyCheckability();
mutablePropertiesIndexes.stream().forEach(i -> {
// This is kindly borrowed from org.hibernate.type.TypeHelper.findDirty
final boolean dirty = currentState[i] != LazyPropertyInitializer.UNFETCHED_PROPERTY && // Consider mutable properties as dirty if we don't have a previous state
(previousState == null || previousState[i] == LazyPropertyInitializer.UNFETCHED_PROPERTY || (propertyCheckability[i] && propertyTypes[i].isDirty(previousState[i], currentState[i], propertyColumnUpdateable[i], session)));
if (dirty) {
fields.add(i);
}
});
}
if (attributeNames.length != 0) {
final boolean[] propertyUpdateability = entityMetamodel.getPropertyUpdateability();
// Sort attribute names so that we can traverse mappings efficiently
Arrays.sort(attributeNames);
int index = 0;
for (final AttributeMapping attributeMapping : attributeMappings) {
final String attributeName = attributeMapping.getAttributeName();
final int nameLength = attributeName.length();
final String currentAttributeName = attributeNames[index];
int position = ((StateArrayContributorMapping) attributeMapping).getStateArrayPosition();
if (currentAttributeName.startsWith(attributeName) && ((currentAttributeName.length() == nameLength || currentAttributeName.charAt(nameLength) == '.'))) {
if (propertyUpdateability[position] && !fields.contains(position)) {
fields.add(position);
}
index++;
if (index < attributeNames.length) {
// Skip duplicates
do {
if (attributeNames[index].equals(attributeName)) {
index++;
} else {
break;
}
} while (index < attributeNames.length);
} else {
break;
}
}
}
}
return ArrayHelper.toIntArray(fields);
}
use of org.hibernate.metamodel.mapping.StateArrayContributorMapping in project hibernate-orm by hibernate.
the class AbstractEntityPersister method setPropertyValues.
@Override
public void setPropertyValues(Object object, Object[] values) {
if (accessOptimizer != null) {
accessOptimizer.setPropertyValues(object, values);
} else {
if (hasSubclasses()) {
visitAttributeMappings(attribute -> {
final int stateArrayPosition = ((StateArrayContributorMapping) attribute).getStateArrayPosition();
final Object value = values[stateArrayPosition];
if (value != UNFETCHED_PROPERTY) {
final Setter setter = attribute.getPropertyAccess().getSetter();
setter.set(object, value);
}
});
} else {
visitFetchables(fetchable -> {
final AttributeMapping attribute = (AttributeMapping) fetchable;
final int stateArrayPosition = ((StateArrayContributorMapping) attribute).getStateArrayPosition();
final Object value = values[stateArrayPosition];
if (value != UNFETCHED_PROPERTY) {
final Setter setter = attribute.getPropertyAccess().getSetter();
setter.set(object, value);
}
}, null);
}
}
}
Aggregations