Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1806,7 +1806,7 @@
final Object entity,
final SharedSessionContractImplementor session,
final EntityEntry entry,
final CacheEntry cacheEntry) {

Check notice

Code scanning / CodeQL

Deprecated method or constructor invocation Note

Invoking
AbstractEntityPersister.getDiscriminatorAlias
should be avoided because it has been deprecated.

LOG.trace( "Initializing lazy properties from second-level cache" );

Expand Down Expand Up @@ -1842,7 +1842,7 @@
final String fieldName,
final Object entity,
final EntityEntry entry,
final int index,

Check notice

Code scanning / CodeQL

Deprecated method or constructor invocation Note

Invoking
AbstractEntityPersister.getSubclassColumnAliasClosure
should be avoided because it has been deprecated.
final Object propValue) {
setPropertyValue( entity, lazyPropertyNumbers[index], propValue );
if ( entry.getLoadedState() != null ) {
Expand Down Expand Up @@ -1999,61 +1999,62 @@
// Wrap expressions with aliases
final SelectClause selectClause = rootQuerySpec.getSelectClause();
final List<SqlSelection> sqlSelections = selectClause.getSqlSelections();
final Set<String> processedExpressions = new HashSet<>( sqlSelections.size() );
int i = 0;
int columnIndex = 0;
final String[] columnAliases = getSubclassColumnAliasClosure();
final int columnAliasesSize = columnAliases.length;
for ( String identifierAlias : identifierAliases ) {
sqlSelections.set(
i,
new SqlSelectionImpl(
i,
new AliasedExpression( sqlSelections.get( i ).getExpression(), identifierAlias + suffix )
)
);
if ( i < columnAliasesSize && columnAliases[i].equals( identifierAlias ) ) {
columnIndex++;
final int identifierSelectionSize = identifierMapping.getJdbcTypeCount();
for ( int j = 0; j < identifierSelectionSize; j++ ) {
final SelectableMapping selectableMapping = identifierMapping.getSelectable( j );
if ( processedExpressions.add( selectableMapping.getSelectionExpression() ) ) {
aliasSelection( sqlSelections, i, identifierAliases[j] + suffix );
i++;
}
i++;
}

if ( entityMetamodel.hasSubclasses() ) {
sqlSelections.set(
i,
new SqlSelectionImpl(
i,
new AliasedExpression( sqlSelections.get( i ).getExpression(), getDiscriminatorAlias() + suffix )
)
);
i++;
if ( hasSubclasses() ) {
assert discriminatorMapping.getJdbcTypeCount() == 1;
final SelectableMapping selectableMapping = discriminatorMapping.getSelectable( 0 );
if ( processedExpressions.add( selectableMapping.getSelectionExpression() ) ) {
aliasSelection( sqlSelections, i, getDiscriminatorAlias() + suffix );
i++;
}
}

if ( hasRowId() ) {
sqlSelections.set(
i,
new SqlSelectionImpl(
i,
new AliasedExpression( sqlSelections.get( i ).getExpression(), ROWID_ALIAS + suffix )
)
);
i++;
final SelectableMapping selectableMapping = rowIdMapping;
if ( processedExpressions.add( selectableMapping.getSelectionExpression() ) ) {
aliasSelection( sqlSelections, i, 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 = !columnReference.isColumnExpressionFormula()
? columnAliases[columnIndex++] + suffix
: formulaAliases[formulaIndex++] + suffix;
sqlSelections.set(
i,
new SqlSelectionImpl(
sqlSelection.getValuesArrayPosition(),
new AliasedExpression( sqlSelection.getExpression(), selectAlias )
)
);
final int size = getNumberOfFetchables();
// getSubclassColumnAliasClosure contains the _identifierMapper columns when it has an id class,
// which need to be skipped
if ( identifierMapping instanceof NonAggregatedIdentifierMapping
&& ( (NonAggregatedIdentifierMapping) identifierMapping ).getIdClassEmbeddable() != null ) {
columnIndex = identifierSelectionSize;
}
for ( int j = 0; j < size; j++ ) {
final AttributeMapping fetchable = getFetchable( j );
if ( !(fetchable instanceof PluralAttributeMapping)
&& !skipFetchable( fetchable, fetchable.getMappedFetchOptions().getTiming() )
&& fetchable.isSelectable() ) {
final int jdbcTypeCount = fetchable.getJdbcTypeCount();
for ( int k = 0; k < jdbcTypeCount; k++ ) {
final SelectableMapping selectableMapping = fetchable.getSelectable( k );
if ( processedExpressions.add( selectableMapping.getSelectionExpression() ) ) {
final String baseAlias = selectableMapping.isFormula()
? formulaAliases[formulaIndex++]
: columnAliases[columnIndex++];
aliasSelection( sqlSelections, i, baseAlias + suffix );
i++;
}
}
}
}

final String sql = getFactory().getJdbcServices()
Expand All @@ -2073,6 +2074,17 @@
return expression;
}

private static void aliasSelection(
List<SqlSelection> sqlSelections,
int selectionIndex,
String alias) {
final Expression expression = sqlSelections.get( selectionIndex ).getExpression();
sqlSelections.set(
selectionIndex,
new SqlSelectionImpl( selectionIndex, new AliasedExpression( expression, alias ) )
);
}

private ImmutableFetchList fetchProcessor(FetchParent fetchParent, LoaderSqlAstCreationState creationState) {
final FetchableContainer fetchableContainer = fetchParent.getReferencedMappingContainer();
final int size = fetchableContainer.getNumberOfFetchables();
Expand All @@ -2083,45 +2095,45 @@
// Ignore plural attributes
if ( !( fetchable instanceof PluralAttributeMapping ) ) {
final FetchTiming fetchTiming = fetchable.getMappedFetchOptions().getTiming();
if ( fetchable.asBasicValuedModelPart() != null ) {
// Ignore lazy basic columns
if ( fetchTiming == FetchTiming.DELAYED ) {
continue;
if ( !skipFetchable( fetchable, fetchTiming ) ) {
if ( fetchTiming == null ) {
throw new AssertionFailure( "fetchTiming was null" );
}
}
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 ) {
continue;
}
// Ensure the FK comes from the root table
if ( !getRootTableName().equals( association.getForeignKeyDescriptor().getKeyTable() ) ) {
continue;
if ( fetchable.isSelectable() ) {
final Fetch fetch = fetchParent.generateFetchableFetch(
fetchable,
fetchParent.resolveNavigablePath( fetchable ),
fetchTiming,
false,
null,
creationState
);
fetches.add( fetch );
}
}

if ( fetchTiming == null ) {
throw new AssertionFailure("fetchTiming was null");
}

if ( fetchable.isSelectable() ) {
final Fetch fetch = fetchParent.generateFetchableFetch(
fetchable,
fetchParent.resolveNavigablePath( fetchable ),
fetchTiming,
false,
null,
creationState
);
fetches.add( fetch );
}
}
}

return fetches.build();
}

private boolean skipFetchable(Fetchable fetchable, FetchTiming fetchTiming) {
if ( fetchable.asBasicValuedModelPart() != null ) {
// Ignore lazy basic columns
return fetchTiming == FetchTiming.DELAYED;
}
else if ( fetchable instanceof Association ) {
final Association association = (Association) fetchable;
// Ignore the fetchable if the FK is on the other side
return association.getSideNature() == ForeignKeyDescriptor.Nature.TARGET
// Ensure the FK comes from the root table
|| !getRootTableName().equals( association.getForeignKeyDescriptor().getKeyTable() );
}
else {
return false;
}
}

/**
* @deprecated use {@link Fetchable#isSelectable()} instead.
*/
Expand Down Expand Up @@ -6354,7 +6366,7 @@
}

@Override
public Fetchable getFetchable(int position) {
public AttributeMapping getFetchable(int position) {
return getStaticFetchableList().get( position );
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.orm.test.query.sql;

import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Entity;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.Jira;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;

@DomainModel(annotatedClasses = {
NativeQueryResultBuilderColumnDeduplicationTest.MyEntity.class
})
@SessionFactory
@Jira("https://hibernate.atlassian.net/browse/HHH-19712")
public class NativeQueryResultBuilderColumnDeduplicationTest {

@Test
public void test(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createNativeQuery( "select {t.*} from MyEntity t", Object.class )
.addEntity( "t", MyEntity.class )
.getResultList();
}
);
}

@Entity(name = "MyEntity")
public static class MyEntity {
@EmbeddedId
private MyEntityPk id;
@Column(insertable = false, updatable = false)
private String name;
private String description;
}

@Embeddable
public static class MyEntityPk {
private String id;
private String name;
}
}
Loading