Move where package to orm.test and further improve result set mapping support

This commit is contained in:
Christian Beikov 2021-04-29 09:03:16 +02:00
parent 8936034d29
commit fef3e53132
84 changed files with 1557 additions and 549 deletions

View File

@ -8,6 +8,7 @@ package org.hibernate.engine.query.internal;
import org.hibernate.engine.query.spi.NativeQueryInterpreter;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.results.ResultSetMapping;
import org.hibernate.query.sql.internal.NativeSelectQueryPlanImpl;
import org.hibernate.query.sql.internal.ParameterParser;
import org.hibernate.query.sql.spi.NativeSelectQueryDefinition;
@ -36,7 +37,7 @@ public class NativeQueryInterpreterStandardImpl implements NativeQueryInterprete
queryDefinition.getSqlString(),
queryDefinition.getAffectedTableNames(),
queryDefinition.getQueryParameterList(),
queryDefinition.getJdbcValuesMappingProducer(),
(ResultSetMapping) queryDefinition.getJdbcValuesMappingProducer(),
queryDefinition.getRowTransformer(),
sessionFactory
);

View File

@ -9,6 +9,7 @@ package org.hibernate.engine.query.spi;
import org.hibernate.Incubating;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.results.ResultSetMapping;
import org.hibernate.query.sql.internal.NativeSelectQueryPlanImpl;
import org.hibernate.query.sql.spi.NativeNonSelectQueryDefinition;
import org.hibernate.query.sql.spi.NativeNonSelectQueryPlan;
@ -45,7 +46,7 @@ public interface NativeQueryInterpreter extends Service {
queryDefinition.getSqlString(),
queryDefinition.getAffectedTableNames(),
queryDefinition.getQueryParameterList(),
queryDefinition.getJdbcValuesMappingProducer(),
(ResultSetMapping) queryDefinition.getJdbcValuesMappingProducer(),
queryDefinition.getRowTransformer(),
sessionFactory
);

View File

@ -7,6 +7,7 @@
package org.hibernate.internal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
@ -151,12 +152,24 @@ public class FilterHelper {
}
}
public static FilterPredicate createFilterPredicate(LoadQueryInfluencers loadQueryInfluencers, Joinable joinable) {
return createFilterPredicate( loadQueryInfluencers, joinable, null );
public static FilterPredicate createFilterPredicate(
LoadQueryInfluencers loadQueryInfluencers,
Joinable joinable,
TableGroup rootTableGroup) {
return createFilterPredicate( loadQueryInfluencers, joinable, rootTableGroup, true );
}
public static FilterPredicate createFilterPredicate(LoadQueryInfluencers loadQueryInfluencers, Joinable joinable, TableGroup rootTableGroup) {
final String filterFragment = joinable.filterFragment( rootTableGroup, loadQueryInfluencers.getEnabledFilters() );
public static FilterPredicate createFilterPredicate(
LoadQueryInfluencers loadQueryInfluencers,
Joinable joinable,
TableGroup rootTableGroup,
boolean useIdentificationVariable) {
final String filterFragment = joinable.filterFragment(
rootTableGroup,
loadQueryInfluencers.getEnabledFilters(),
Collections.emptySet(),
useIdentificationVariable
);
if ( StringHelper.isNotEmpty( filterFragment ) ) {
return doCreateFilterPredicate( filterFragment, loadQueryInfluencers.getEnabledFilters() );
}

View File

@ -101,7 +101,7 @@ class DatabaseSnapshotExecutor {
state.getFromClauseAccess().registerTableGroup( rootPath, rootTableGroup );
// We produce the same state array as if we were creating an entity snapshot
final List<DomainResult> domainResults = new ArrayList<>();
final List<DomainResult<?>> domainResults = new ArrayList<>();
final SqlExpressionResolver sqlExpressionResolver = state.getSqlExpressionResolver();

View File

@ -95,44 +95,6 @@ import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnRefere
public class LoaderSelectBuilder {
private static final Logger log = Logger.getLogger( LoaderSelectBuilder.class );
/**
* Create an SQL AST select-statement based on matching one-or-more keys
*
* @param loadable The root Loadable
* @param partsToSelect Parts of the Loadable to select. Null/empty indicates to select the Loadable itself
* @param restrictedPart Part to base the where-clause restriction on
* @param cachedDomainResult DomainResult to be used. Null indicates to generate the DomainResult
* @param numberOfKeysToLoad How many keys should be accounted for in the where-clause restriction?
* @param loadQueryInfluencers Any influencers (entity graph, fetch profile) to account for
* @param lockOptions Pessimistic lock options to apply
* @param jdbcParameterConsumer Consumer for all JdbcParameter references created
* @param sessionFactory The SessionFactory
*/
public static SelectStatement createSelect(
Loadable loadable,
List<? extends ModelPart> partsToSelect,
ModelPart restrictedPart,
DomainResult<?> cachedDomainResult,
int numberOfKeysToLoad,
LoadQueryInfluencers loadQueryInfluencers,
LockOptions lockOptions,
Consumer<JdbcParameter> jdbcParameterConsumer,
SessionFactoryImplementor sessionFactory) {
final LoaderSelectBuilder process = new LoaderSelectBuilder(
sessionFactory,
loadable,
partsToSelect,
restrictedPart,
cachedDomainResult,
numberOfKeysToLoad,
loadQueryInfluencers,
lockOptions,
jdbcParameterConsumer
);
return process.generateSelect();
}
/**
* Create an SQL AST select-statement for a select by unique key based on matching one-or-more keys
*
@ -173,6 +135,44 @@ public class LoaderSelectBuilder {
return process.generateSelect();
}
/**
* Create an SQL AST select-statement based on matching one-or-more keys
*
* @param loadable The root Loadable
* @param partsToSelect Parts of the Loadable to select. Null/empty indicates to select the Loadable itself
* @param restrictedPart Part to base the where-clause restriction on
* @param cachedDomainResult DomainResult to be used. Null indicates to generate the DomainResult
* @param numberOfKeysToLoad How many keys should be accounted for in the where-clause restriction?
* @param loadQueryInfluencers Any influencers (entity graph, fetch profile) to account for
* @param lockOptions Pessimistic lock options to apply
* @param jdbcParameterConsumer Consumer for all JdbcParameter references created
* @param sessionFactory The SessionFactory
*/
public static SelectStatement createSelect(
Loadable loadable,
List<? extends ModelPart> partsToSelect,
ModelPart restrictedPart,
DomainResult<?> cachedDomainResult,
int numberOfKeysToLoad,
LoadQueryInfluencers loadQueryInfluencers,
LockOptions lockOptions,
Consumer<JdbcParameter> jdbcParameterConsumer,
SessionFactoryImplementor sessionFactory) {
final LoaderSelectBuilder process = new LoaderSelectBuilder(
sessionFactory,
loadable,
partsToSelect,
restrictedPart,
cachedDomainResult,
numberOfKeysToLoad,
loadQueryInfluencers,
lockOptions,
jdbcParameterConsumer
);
return process.generateSelect();
}
public static SelectStatement createSelect(
Loadable loadable,
List<? extends ModelPart> partsToSelect,
@ -444,6 +444,9 @@ public class LoaderSelectBuilder {
applyFiltering( rootQuerySpec, rootTableGroup, pluralAttributeMapping );
applyOrdering( rootTableGroup, pluralAttributeMapping );
}
else if ( loadable instanceof Joinable ) {
applyFiltering( rootQuerySpec, rootTableGroup, (Joinable) loadable );
}
if ( orderByFragments != null ) {
orderByFragments.forEach(
@ -455,7 +458,7 @@ public class LoaderSelectBuilder {
);
}
return new SelectStatement( rootQuerySpec, (List) domainResults );
return new SelectStatement( rootQuerySpec, domainResults );
}
private void applyRestriction(
@ -575,6 +578,20 @@ public class LoaderSelectBuilder {
}
}
private void applyFiltering(
QuerySpec querySpec,
TableGroup tableGroup,
Joinable joinable) {
final Predicate filterPredicate = FilterHelper.createFilterPredicate(
loadQueryInfluencers,
joinable,
tableGroup
);
if ( filterPredicate != null ) {
querySpec.applyPredicate( filterPredicate );
}
}
private void applyOrdering(TableGroup tableGroup, PluralAttributeMapping pluralAttributeMapping) {
if ( pluralAttributeMapping.getOrderByFragment() != null ) {
applyOrdering( tableGroup, pluralAttributeMapping.getOrderByFragment() );

View File

@ -1789,7 +1789,8 @@ public abstract class AbstractCollectionPersister
buffer.append( " and " );
}
assert elementPersister instanceof Joinable;
buffer.append( StringHelper.replace( manyToManyWhereTemplate, Template.TEMPLATE, ( (Joinable) elementPersister ).getTableName() ) );
final TableReference tableReference = tableGroup.getTableReference( ( (Joinable) elementPersister ).getTableName() );
buffer.append( StringHelper.replace( manyToManyWhereTemplate, Template.TEMPLATE, tableReference.getIdentificationVariable() ) );
}
return buffer.toString();
@ -1940,11 +1941,9 @@ public abstract class AbstractCollectionPersister
public String filterFragment(
TableGroup tableGroup,
Map<String, Filter> enabledFilters,
Set<String> treatAsDeclarations) {
StringBuilder sessionFilterFragment = new StringBuilder();
filterHelper.render( sessionFilterFragment, getFilterAliasGenerator( tableGroup ), enabledFilters );
TableReference tableReference = null;
Set<String> treatAsDeclarations,
boolean useIdentificationVariable) {
TableReference tableReference;
if ( isManyToMany() ) {
// if filtering on many-to-many element were intended, getManyToManyFilterFragment() should have been chosen
tableReference = tableGroup.getPrimaryTableReference();
@ -1952,11 +1951,23 @@ public abstract class AbstractCollectionPersister
else if ( elementPersister instanceof Joinable ) {
tableReference = tableGroup.getTableReference( tableGroup.getNavigablePath(), ( (Joinable) elementPersister ).getTableName() );
}
if ( tableReference != null ) {
sessionFilterFragment.append( filterFragment( tableReference.getIdentificationVariable(), treatAsDeclarations ) );
else {
tableReference = tableGroup.getTableReference( tableGroup.getNavigablePath(), qualifiedTableName );
}
return sessionFilterFragment.toString();
final String alias;
if ( tableReference == null ) {
alias = null;
}
else if ( useIdentificationVariable && tableReference.getIdentificationVariable() != null ) {
alias = tableReference.getIdentificationVariable();
}
else {
alias = tableReference.getTableExpression();
}
StringBuilder sessionFilterFragment = new StringBuilder();
filterHelper.render( sessionFilterFragment, getFilterAliasGenerator( tableGroup ), enabledFilters );
return sessionFilterFragment.append( filterFragment( alias, treatAsDeclarations ) ).toString();
}
@Override

View File

@ -4208,10 +4208,24 @@ public abstract class AbstractEntityPersister
}
@Override
public String filterFragment(TableGroup tableGroup, Map<String, Filter> enabledFilters, Set<String> treatAsDeclarations) {
public String filterFragment(
TableGroup tableGroup,
Map<String, Filter> enabledFilters,
Set<String> treatAsDeclarations,
boolean useIdentificationVariable) {
final String alias;
if ( tableGroup == null ) {
alias = null;
}
else if ( useIdentificationVariable && tableGroup.getPrimaryTableReference().getIdentificationVariable() != null ) {
alias = tableGroup.getPrimaryTableReference().getIdentificationVariable();
}
else {
alias = tableGroup.getPrimaryTableReference().getTableExpression();
}
final StringBuilder sessionFilterFragment = new StringBuilder();
filterHelper.render( sessionFilterFragment, tableGroup == null ? null : getFilterAliasGenerator( tableGroup ), enabledFilters );
return sessionFilterFragment.append( filterFragment( tableGroup == null ? null : tableGroup.getPrimaryTableReference().getIdentificationVariable(), treatAsDeclarations ) ).toString();
filterHelper.render( sessionFilterFragment, !useIdentificationVariable || tableGroup == null ? null : getFilterAliasGenerator( tableGroup ), enabledFilters );
return sessionFilterFragment.append( filterFragment( alias, treatAsDeclarations ) ).toString();
}
public String generateFilterConditionAlias(String rootAlias) {

View File

@ -85,16 +85,16 @@ public interface Joinable {
return filterFragment( alias, enabledFilters, Collections.emptySet() );
}
public default String filterFragment(TableGroup tableGroup, Map<String, Filter> enabledFilters) throws MappingException {
return filterFragment( tableGroup, enabledFilters, Collections.emptySet() );
}
/**
* Get the where clause filter, given a query alias and considering enabled session filters
*/
public String filterFragment(String alias, Map<String, Filter> enabledFilters, Set<String> treatAsDeclarations) throws MappingException;
public String filterFragment(TableGroup tableGroup, Map<String, Filter> enabledFilters, Set<String> treatAsDeclarations) throws MappingException;
public String filterFragment(
TableGroup tableGroup,
Map<String, Filter> enabledFilters,
Set<String> treatAsDeclarations,
boolean useIdentificationVariable) throws MappingException;
public String oneToManyFilterFragment(String alias) throws MappingException;

View File

@ -26,7 +26,7 @@ import org.hibernate.FlushMode;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.MappingException;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.metamodel.model.domain.BasicDomainType;
import org.hibernate.transform.ResultTransformer;
@ -382,6 +382,15 @@ public interface NativeQuery<T> extends Query<T>, SynchronizeableQuery {
* result sets.
*/
interface RootReturn extends ReturnableResultNode {
String getTableAlias();
String getDiscriminatorAlias();
EntityMappingType getEntityMapping();
NavigablePath getNavigablePath();
/**
* Set the lock mode for this return.
*
@ -391,10 +400,7 @@ public interface NativeQuery<T> extends Query<T>, SynchronizeableQuery {
*/
RootReturn setLockMode(LockMode lockMode);
default RootReturn addIdColumnAliases(String... aliases){
throw new NotYetImplementedFor6Exception( getClass() );
}
RootReturn addIdColumnAliases(String... aliases);
/**
* Name the column alias that identifies the entity's discriminator.
@ -430,6 +436,13 @@ public interface NativeQuery<T> extends Query<T>, SynchronizeableQuery {
* from result sets.
*/
interface FetchReturn extends ResultNode {
String getTableAlias();
String getOwnerAlias();
String getFetchableName();
/**
* Set the lock mode for this return.
*

View File

@ -13,6 +13,7 @@ import javax.persistence.metamodel.SingularAttribute;
import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.RuntimeMetamodels;
import org.hibernate.metamodel.mapping.AttributeMapping;
@ -20,6 +21,7 @@ import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
import org.hibernate.metamodel.mapping.internal.EntityCollectionPart;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.NavigablePath;
@ -38,8 +40,12 @@ import org.hibernate.query.results.implicit.ImplicitFetchBuilderEmbeddable;
import org.hibernate.query.results.implicit.ImplicitFetchBuilderEntity;
import org.hibernate.query.results.implicit.ImplicitFetchBuilderPlural;
import org.hibernate.query.results.implicit.ImplicitModelPartResultBuilderEntity;
import org.hibernate.sql.ast.spi.FromClauseAccess;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.collection.internal.EntityCollectionPartTableGroup;
import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable;
import org.hibernate.sql.results.graph.entity.EntityValuedFetchable;
import org.hibernate.type.BasicType;
@ -213,7 +219,7 @@ public class Builders {
String tableAlias,
String entityName,
SessionFactoryImplementor sessionFactory) {
return entityCalculated( tableAlias, entityName, null,sessionFactory );
return entityCalculated( tableAlias, entityName, null, sessionFactory );
}
/**
@ -235,7 +241,7 @@ public class Builders {
}
public static DynamicFetchBuilderLegacy fetch(String tableAlias, String ownerTableAlias, String joinPropertyName) {
throw new NotYetImplementedFor6Exception( );
return new DynamicFetchBuilderLegacy( tableAlias, ownerTableAlias, joinPropertyName, null );
}
public static ResultBuilder implicitEntityResultBuilder(
@ -271,6 +277,28 @@ public class Builders {
return new ImplicitFetchBuilderPlural( fetchPath, (PluralAttributeMapping) fetchable, creationState );
}
if ( fetchable instanceof EntityCollectionPart ) {
final EntityCollectionPart entityCollectionPart = (EntityCollectionPart) fetchable;
return (parent, fetchablePath, jdbcResultsMetadata, legacyFetchResolver, domainResultCreationState) -> {
final FromClauseAccess fromClauseAccess = domainResultCreationState.getSqlAstCreationState()
.getFromClauseAccess();
final TableGroup collectionTableGroup = fromClauseAccess.findTableGroup( parent.getNavigablePath() );
fromClauseAccess.registerTableGroup(
fetchablePath,
new EntityCollectionPartTableGroup( fetchablePath, collectionTableGroup, entityCollectionPart )
);
return parent.generateFetchableFetch(
entityCollectionPart,
fetchablePath,
FetchTiming.IMMEDIATE,
true,
LockMode.NONE,
null,
domainResultCreationState
);
};
}
throw new UnsupportedOperationException();
}
}

View File

@ -337,9 +337,24 @@ public class DomainResultCreationStateImpl
final FetchBuilder explicitFetchBuilder = fetchBuilderResolverStack
.getCurrent()
.apply( relativePath.getFullPath() );
final FetchBuilder fetchBuilder = explicitFetchBuilder != null
? explicitFetchBuilder
: Builders.implicitFetchBuilder( fetchPath, fetchable, this );
final FetchBuilder fetchBuilder;
if ( explicitFetchBuilder != null ) {
fetchBuilder = explicitFetchBuilder;
}
else {
final DynamicFetchBuilderLegacy fetchBuilderLegacy = legacyFetchResolver.resolve(
fromClauseAccess.findTableGroup( fetchParent.getNavigablePath() )
.getPrimaryTableReference()
.getIdentificationVariable(),
fetchableName
);
if ( fetchBuilderLegacy == null ) {
fetchBuilder = Builders.implicitFetchBuilder( fetchPath, fetchable, this );
}
else {
fetchBuilder = fetchBuilderLegacy;
}
}
final Fetch fetch = fetchBuilder.buildFetch(
fetchParent,
fetchPath,

View File

@ -6,50 +6,30 @@
*/
package org.hibernate.query.results;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMapping;
import org.hibernate.sql.results.jdbc.internal.StandardJdbcValuesMapping;
/**
* Implementation of JdbcValuesMapping for native / procedure queries
*
* @author Steve Ebersole
*/
public class JdbcValuesMappingImpl implements JdbcValuesMapping {
private final List<SqlSelection> sqlSelections;
private final List<DomainResult<?>> domainResults;
public class JdbcValuesMappingImpl extends StandardJdbcValuesMapping {
private final int rowSize;
public JdbcValuesMappingImpl(
List<SqlSelection> sqlSelections,
List<DomainResult<?>> domainResults) {
this.sqlSelections = sqlSelections;
this.domainResults = domainResults;
List<DomainResult<?>> domainResults, int rowSize) {
super( sqlSelections, domainResults );
this.rowSize = rowSize;
}
@Override
public List<SqlSelection> getSqlSelections() {
return sqlSelections;
}
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public List<DomainResult> getDomainResults() {
return (List) domainResults;
}
@Override
@SuppressWarnings("rawtypes")
public List<DomainResultAssembler> resolveAssemblers(AssemblerCreationState creationState) {
final List<DomainResultAssembler> assemblers = new ArrayList<>( domainResults.size() );
domainResults.forEach(
domainResult -> assemblers.add( domainResult.createResultAssembler( creationState ) )
);
return assemblers;
public int getRowSize() {
return rowSize;
}
}

View File

@ -7,6 +7,7 @@
package org.hibernate.query.results;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import org.hibernate.Incubating;
import org.hibernate.query.named.NamedResultSetMappingMemento;
@ -40,6 +41,7 @@ public interface ResultSetMapping extends JdbcValuesMappingProducer {
int getNumberOfResultBuilders();
void visitResultBuilders(BiConsumer<Integer, ResultBuilder> resultBuilderConsumer);
void visitLegacyFetchBuilders(Consumer<DynamicFetchBuilderLegacy> resultBuilderConsumer);
void addResultBuilder(ResultBuilder resultBuilder);
void addLegacyFetchBuilder(DynamicFetchBuilderLegacy fetchBuilder);

View File

@ -66,6 +66,19 @@ public class ResultSetMappingImpl implements ResultSetMapping {
}
}
@Override
public void visitLegacyFetchBuilders(Consumer<DynamicFetchBuilderLegacy> resultBuilderConsumer) {
if ( legacyFetchBuilders == null ) {
return;
}
for ( Map.Entry<String, Map<String, DynamicFetchBuilderLegacy>> entry : legacyFetchBuilders.entrySet() ) {
for ( DynamicFetchBuilderLegacy fetchBuilder : entry.getValue().values() ) {
resultBuilderConsumer.accept( fetchBuilder );
}
}
}
@Override
public void addResultBuilder(ResultBuilder resultBuilder) {
if ( resultBuilders == null ) {
@ -120,15 +133,16 @@ public class ResultSetMappingImpl implements ResultSetMapping {
SessionFactoryImplementor sessionFactory) {
final int numberOfResults;
final int rowSize = jdbcResultsMetadata.getColumnCount();
if ( resultBuilders == null ) {
numberOfResults = jdbcResultsMetadata.getColumnCount();
numberOfResults = rowSize;
}
else {
numberOfResults = resultBuilders.size();
}
final List<SqlSelection> sqlSelections = new ArrayList<>( jdbcResultsMetadata.getColumnCount() );
final List<SqlSelection> sqlSelections = new ArrayList<>( rowSize );
final List<DomainResult<?>> domainResults = new ArrayList<>( numberOfResults );
final DomainResultCreationStateImpl creationState = new DomainResultCreationStateImpl(
@ -169,7 +183,7 @@ public class ResultSetMappingImpl implements ResultSetMapping {
domainResults.add( domainResult );
}
return new JdbcValuesMappingImpl( sqlSelections, domainResults );
return new JdbcValuesMappingImpl( sqlSelections, domainResults, rowSize );
}
private DomainResult<?> makeImplicitDomainResult(

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.query.results;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
@ -28,7 +29,8 @@ public class TableGroupImpl implements TableGroup {
private final NavigablePath navigablePath;
private final String alias;
private final TableReferenceImpl primaryTableReference;
private final TableReference primaryTableReference;
private List<TableGroupJoin> tableGroupJoins;
private final ModelPartContainer container;
private final LockMode lockMode;
@ -37,7 +39,7 @@ public class TableGroupImpl implements TableGroup {
public TableGroupImpl(
NavigablePath navigablePath,
String alias,
TableReferenceImpl primaryTableReference,
TableReference primaryTableReference,
ModelPartContainer container,
LockMode lockMode) {
this.navigablePath = navigablePath;
@ -74,21 +76,29 @@ public class TableGroupImpl implements TableGroup {
@Override
public List<TableGroupJoin> getTableGroupJoins() {
return Collections.emptyList();
return tableGroupJoins == null ? Collections.emptyList() : Collections.unmodifiableList( tableGroupJoins );
}
@Override
public boolean hasTableGroupJoins() {
return false;
return tableGroupJoins != null && !tableGroupJoins.isEmpty();
}
@Override
public void addTableGroupJoin(TableGroupJoin join) {
throw new UnsupportedOperationException();
if ( tableGroupJoins == null ) {
tableGroupJoins = new ArrayList<>();
}
if ( !tableGroupJoins.contains( join ) ) {
tableGroupJoins.add( join );
}
}
@Override
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
if ( tableGroupJoins != null ) {
tableGroupJoins.forEach( consumer );
}
}
@Override
@ -113,21 +123,28 @@ public class TableGroupImpl implements TableGroup {
@Override
public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
return primaryTableReference;
final TableReference tableReference = getTableReference( navigablePath, tableExpression );
if ( tableReference == null ) {
throw new IllegalStateException( "Could not resolve binding for table `" + tableExpression + "`" );
}
return tableReference;
}
@Override
public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
return primaryTableReference;
if ( primaryTableReference.getTableReference( navigablePath , tableExpression ) != null ) {
return primaryTableReference;
}
for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) {
final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference();
if ( primaryTableReference.getTableReference( navigablePath, tableExpression ) != null ) {
return primaryTableReference;
}
}
return null;
}
public static class TableReferenceImpl extends TableReference {
public TableReferenceImpl(
String tableExpression,
String identificationVariable,
boolean isOptional,
SessionFactoryImplementor sessionFactory) {
super( tableExpression, identificationVariable, isOptional, sessionFactory );
}
}
}

View File

@ -14,6 +14,7 @@ import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.results.graph.DomainResultCreationState;
@ -65,13 +66,14 @@ public class CompleteResultBuilderBasicModelPart
final TableReference tableReference = tableGroup.getTableReference( navigablePath, modelPart.getContainingTableExpression() );
final String mappedColumn = modelPart.getSelectionExpression();
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition );
creationStateImpl.resolveSqlSelection(
final SqlSelection sqlSelection = creationStateImpl.resolveSqlSelection(
creationStateImpl.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( tableReference, mappedColumn ),
processingState -> new SqlSelectionImpl( valuesArrayPosition, modelPart )
processingState -> {
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition );
return new SqlSelectionImpl( valuesArrayPosition, modelPart );
}
),
modelPart.getJavaTypeDescriptor(),
creationStateImpl.getSessionFactory().getTypeConfiguration()
@ -79,7 +81,7 @@ public class CompleteResultBuilderBasicModelPart
//noinspection unchecked
return new BasicResult(
valuesArrayPosition,
sqlSelection.getValuesArrayPosition(),
columnAlias,
modelPart.getJavaTypeDescriptor()
);

View File

@ -14,6 +14,7 @@ import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
@ -54,39 +55,46 @@ public class CompleteResultBuilderBasicValuedStandard implements CompleteResultB
final DomainResultCreationStateImpl creationStateImpl = impl( domainResultCreationState );
final SessionFactoryImplementor sessionFactory = creationStateImpl.getSessionFactory();
final int jdbcPosition;
final String columnName;
if ( explicitColumnName != null ) {
jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( explicitColumnName );
columnName = explicitColumnName;
}
else {
jdbcPosition = resultPosition + 1;
columnName = jdbcResultsMetadata.resolveColumnName( jdbcPosition );
columnName = jdbcResultsMetadata.resolveColumnName( resultPosition + 1 );
}
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
final BasicValuedMapping basicType;
if ( explicitType != null ) {
basicType = explicitType;
}
else {
basicType = jdbcResultsMetadata.resolveType( jdbcPosition, explicitJavaTypeDescriptor );
}
creationStateImpl.resolveSqlSelection(
final SqlSelection sqlSelection = creationStateImpl.resolveSqlSelection(
creationStateImpl.resolveSqlExpression(
columnName,
processingState -> new SqlSelectionImpl( valuesArrayPosition, basicType )
processingState -> {
final int jdbcPosition;
if ( explicitColumnName != null ) {
jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( explicitColumnName );
}
else {
jdbcPosition = resultPosition + 1;
}
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
final BasicValuedMapping basicType;
if ( explicitType != null ) {
basicType = explicitType;
}
else {
basicType = jdbcResultsMetadata.resolveType( jdbcPosition, explicitJavaTypeDescriptor );
}
return new SqlSelectionImpl( valuesArrayPosition, basicType );
}
),
explicitJavaTypeDescriptor,
sessionFactory.getTypeConfiguration()
);
return new BasicResult<>( valuesArrayPosition, columnName, basicType.getMappedType().getMappedJavaTypeDescriptor() );
return new BasicResult<>(
sqlSelection.getValuesArrayPosition(),
columnName,
sqlSelection.getExpressionType().getJdbcMappings().get( 0 ).getMappedJavaTypeDescriptor()
);
}
}

View File

@ -72,4 +72,8 @@ public abstract class AbstractFetchBuilderContainer<T extends AbstractFetchBuild
return fetchBuilder;
}
public void addFetchBuilder(String propertyName, DynamicFetchBuilder fetchBuilder) {
fetchBuilderMap.put( propertyName, fetchBuilder );
}
}

View File

@ -10,19 +10,33 @@ import java.util.List;
import java.util.function.BiFunction;
import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAliasBaseConstant;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey;
/**
* @author Steve Ebersole
* @author Christian Beikov
*/
public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQuery.FetchReturn {
@ -32,6 +46,7 @@ public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQue
private final String fetchableName;
private final List<String> columnNames;
private final DynamicResultBuilderEntityStandard resultBuilderEntity;
public DynamicFetchBuilderLegacy(
String tableAlias,
@ -42,16 +57,33 @@ public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQue
this.ownerTableAlias = ownerTableAlias;
this.fetchableName = fetchableName;
this.columnNames = columnNames;
this.resultBuilderEntity = null;
}
public DynamicFetchBuilderLegacy(
String tableAlias,
String ownerTableAlias,
String fetchableName,
List<String> columnNames,
DynamicResultBuilderEntityStandard resultBuilderEntity) {
this.tableAlias = tableAlias;
this.ownerTableAlias = ownerTableAlias;
this.fetchableName = fetchableName;
this.columnNames = columnNames;
this.resultBuilderEntity = resultBuilderEntity;
}
@Override
public String getTableAlias() {
return tableAlias;
}
@Override
public String getOwnerAlias() {
return ownerTableAlias;
}
@Override
public String getFetchableName() {
return fetchableName;
}
@ -64,12 +96,88 @@ public class DynamicFetchBuilderLegacy implements DynamicFetchBuilder, NativeQue
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
DomainResultCreationState domainResultCreationState) {
final DomainResultCreationStateImpl creationState = ResultsHelper.impl( domainResultCreationState );
final TableGroup ownerTableGroup = creationState.getFromClauseAccess().findByAlias( ownerTableAlias );
final AttributeMapping attributeMapping = parent.getReferencedMappingContainer()
.findContainingEntityMapping()
.findDeclaredAttributeMapping( fetchableName );
final TableGroup tableGroup;
if ( attributeMapping instanceof TableGroupJoinProducer ) {
final SqlAliasBase sqlAliasBase = new SqlAliasBaseConstant( tableAlias );
final TableGroupJoin tableGroupJoin = ( (TableGroupJoinProducer) attributeMapping ).createTableGroupJoin(
fetchPath,
ownerTableGroup,
tableAlias,
SqlAstJoinType.INNER,
true,
LockMode.NONE,
s -> sqlAliasBase,
creationState.getSqlExpressionResolver(),
creationState.getCreationContext()
);
creationState.getFromClauseAccess().registerTableGroup( fetchPath, tableGroup = tableGroupJoin.getJoinedGroup() );
}
else {
tableGroup = ownerTableGroup;
}
// todo (6.0) : create the TableGroupJoin for the fetch and then build the fetch
final ForeignKeyDescriptor keyDescriptor;
if ( attributeMapping instanceof PluralAttributeMapping ) {
final PluralAttributeMapping pluralAttributeMapping = (PluralAttributeMapping) attributeMapping;
keyDescriptor = pluralAttributeMapping.getKeyDescriptor();
}
else {
// Not sure if this fetch builder can also be used with other attribute mappings
assert attributeMapping instanceof ToOneAttributeMapping;
throw new NotYetImplementedFor6Exception( getClass() );
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
keyDescriptor = toOneAttributeMapping.getForeignKeyDescriptor();
}
keyDescriptor.forEachSelectable(
(selectionIndex, selectableMapping) -> {
resolveSqlSelection(
columnNames.get( selectionIndex ),
createColumnReferenceKey(
tableGroup.getTableReference( selectableMapping.getContainingTableExpression() ),
selectableMapping.getSelectionExpression()
),
selectableMapping.getJdbcMapping(),
jdbcResultsMetadata,
domainResultCreationState
);
}
);
// We process the fetch builder such that it contains a resultBuilderEntity before calling this method in ResultSetMappingProcessor
assert resultBuilderEntity != null;
return resultBuilderEntity.buildFetch(
parent,
attributeMapping,
jdbcResultsMetadata,
creationState
);
}
private void resolveSqlSelection(
String columnAlias,
String columnKey,
JdbcMapping jdbcMapping,
JdbcValuesMetadata jdbcResultsMetadata,
DomainResultCreationState domainResultCreationState) {
final SqlExpressionResolver sqlExpressionResolver = domainResultCreationState.getSqlAstCreationState().getSqlExpressionResolver();
sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression(
columnKey,
state -> {
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
final int valuesArrayPosition = jdbcPosition - 1;
return new SqlSelectionImpl( valuesArrayPosition, jdbcMapping );
}
),
jdbcMapping.getMappedJavaTypeDescriptor(),
domainResultCreationState.getSqlAstCreationState().getCreationContext().getSessionFactory().getTypeConfiguration()
);
}
@Override

View File

@ -10,19 +10,30 @@ import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.LockMode;
import org.hibernate.engine.FetchTiming;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.SelectableConsumer;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey;
/**
* @author Steve Ebersole
* @author Christian Beikov
*/
public class DynamicFetchBuilderStandard
implements DynamicFetchBuilder, NativeQuery.ReturnProperty {
@ -50,9 +61,59 @@ public class DynamicFetchBuilderStandard
final TableGroup ownerTableGroup = creationStateImpl.getFromClauseAccess().getTableGroup( parent.getNavigablePath() );
// todo (6.0) : create the TableGroupJoin for the fetch and then build the fetch
final Fetchable attributeMapping = (Fetchable) parent.getReferencedMappingContainer().findSubPart( fetchableName, null );
final SqlExpressionResolver sqlExpressionResolver = domainResultCreationState.getSqlAstCreationState().getSqlExpressionResolver();
throw new NotYetImplementedFor6Exception( getClass() );
final SelectableConsumer selectableConsumer = (selectionIndex, selectableMapping) -> {
final TableReference tableReference = ownerTableGroup.getTableReference(
fetchPath,
selectableMapping.getContainingTableExpression()
);
final String columnAlias = columnNames.get( selectionIndex );
sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression(
createColumnReferenceKey( tableReference, selectableMapping.getSelectionExpression() ),
state -> {
final int resultSetPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
final int valuesArrayPosition = resultSetPosition - 1;
return new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) selectableMapping );
}
),
selectableMapping.getJdbcMapping().getMappedJavaTypeDescriptor(),
domainResultCreationState.getSqlAstCreationState()
.getCreationContext()
.getSessionFactory()
.getTypeConfiguration()
);
};
if ( attributeMapping instanceof BasicValuedMapping ) {
attributeMapping.forEachSelectable( selectableConsumer );
return parent.generateFetchableFetch(
attributeMapping,
fetchPath,
FetchTiming.IMMEDIATE,
true,
LockMode.NONE,
null,
creationStateImpl
);
}
else {
// Not sure if this fetch builder can also be used with other attribute mappings
assert attributeMapping instanceof ToOneAttributeMapping;
final ToOneAttributeMapping toOneAttributeMapping = (ToOneAttributeMapping) attributeMapping;
toOneAttributeMapping.getForeignKeyDescriptor().visitKeySelectables( selectableConsumer );
return parent.generateFetchableFetch(
attributeMapping,
fetchPath,
FetchTiming.DELAYED,
false,
LockMode.NONE,
null,
creationStateImpl
);
}
}
@Override

View File

@ -11,8 +11,10 @@ import java.util.function.BiFunction;
import org.hibernate.metamodel.mapping.SingularAttributeMapping;
import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.basic.BasicResult;
@ -23,7 +25,7 @@ import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
*
* @author Steve Ebersole
*/
public class DynamicResultBuilderAttribute implements DynamicResultBuilder {
public class DynamicResultBuilderAttribute implements DynamicResultBuilder, NativeQuery.ReturnProperty {
private final BasicAttributeMapping attributeMapping;
private final String columnAlias;
private final String entityName;
@ -53,29 +55,38 @@ public class DynamicResultBuilderAttribute implements DynamicResultBuilder {
this.attributePath = attributePath;
}
@Override
public NativeQuery.ReturnProperty addColumnAlias(String columnAlias) {
throw new UnsupportedOperationException();
}
@Override
public DomainResult<?> buildResult(
JdbcValuesMetadata jdbcResultsMetadata,
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
DomainResultCreationState domainResultCreationState) {
final int resultSetPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
final int valuesArrayPosition = resultSetPosition - 1;
// todo (6.0) : TableGroups + `attributeMapping#buldResult`
final SqlExpressionResolver sqlExpressionResolver = domainResultCreationState.getSqlAstCreationState().getSqlExpressionResolver();
sqlExpressionResolver.resolveSqlSelection(
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression(
columnAlias,
state -> new SqlSelectionImpl( valuesArrayPosition, attributeMapping )
state -> {
final int resultSetPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
final int valuesArrayPosition = resultSetPosition - 1;
return new SqlSelectionImpl( valuesArrayPosition, attributeMapping );
}
),
attributeMapping.getJavaTypeDescriptor(),
domainResultCreationState.getSqlAstCreationState().getCreationContext().getSessionFactory().getTypeConfiguration()
domainResultCreationState.getSqlAstCreationState()
.getCreationContext()
.getSessionFactory()
.getTypeConfiguration()
);
return new BasicResult<>(
valuesArrayPosition,
sqlSelection.getValuesArrayPosition(),
columnAlias,
attributeMapping.getJavaTypeDescriptor(),
attributeMapping.getValueConverter()

View File

@ -19,6 +19,7 @@ import org.hibernate.resource.beans.spi.ManagedBean;
import org.hibernate.resource.beans.spi.ManagedBeanRegistry;
import org.hibernate.resource.beans.spi.ProvidedInstanceManagedBeanImpl;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
@ -97,32 +98,35 @@ public class DynamicResultBuilderBasicConverted<O,R> implements DynamicResultBui
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
DomainResultCreationState domainResultCreationState) {
final int currentJdbcPosition = resultPosition + 1;
final int jdbcPosition;
if ( columnAlias != null ) {
jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
}
else {
jdbcPosition = currentJdbcPosition;
}
final TypeConfiguration typeConfiguration = domainResultCreationState.getSqlAstCreationState()
.getCreationContext()
.getSessionFactory()
.getTypeConfiguration();
final BasicType<?> basicType = jdbcResultsMetadata.resolveType( jdbcPosition, basicValueConverter.getRelationalJavaDescriptor() );
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
final SqlExpressionResolver sqlExpressionResolver = domainResultCreationState.getSqlAstCreationState().getSqlExpressionResolver();
sqlExpressionResolver.resolveSqlExpression(
columnAlias,
state -> new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) basicType )
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression(
columnAlias,
state -> {
final int currentJdbcPosition = resultPosition + 1;
final int jdbcPosition;
if ( columnAlias != null ) {
jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
}
else {
jdbcPosition = currentJdbcPosition;
}
final BasicType<?> basicType = jdbcResultsMetadata.resolveType( jdbcPosition, basicValueConverter.getRelationalJavaDescriptor() );
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
return new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) basicType );
}
),
domainJtd,
typeConfiguration
);
//noinspection unchecked
return new BasicResult( valuesArrayPosition, columnAlias, domainJtd, basicValueConverter );
return new BasicResult<>( sqlSelection.getValuesArrayPosition(), columnAlias, domainJtd, basicValueConverter );
}
}

View File

@ -13,6 +13,8 @@ import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
@ -78,17 +80,24 @@ public class DynamicResultBuilderBasicStandard implements DynamicResultBuilderBa
.getCreationContext()
.getSessionFactory();
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnName );
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
final SqlExpressionResolver sqlExpressionResolver = domainResultCreationState.getSqlAstCreationState().getSqlExpressionResolver();
final Expression expression = sqlExpressionResolver.resolveSqlExpression(
columnName,
state -> {
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnName );
final int valuesArrayPosition = ResultsHelper.jdbcPositionToValuesArrayPosition( jdbcPosition );
final BasicType<?> basicType;
final BasicType<?> basicType;
if ( explicitType != null ) {
basicType = explicitType;
}
else {
basicType = jdbcResultsMetadata.resolveType( jdbcPosition, explicitJavaTypeDescriptor );
}
if ( explicitType != null ) {
basicType = explicitType;
}
else {
basicType = jdbcResultsMetadata.resolveType( jdbcPosition, explicitJavaTypeDescriptor );
}
return new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) basicType );
}
);
final JavaTypeDescriptor<?> javaTypeDescriptor;
@ -96,23 +105,18 @@ public class DynamicResultBuilderBasicStandard implements DynamicResultBuilderBa
javaTypeDescriptor = explicitJavaTypeDescriptor;
}
else {
javaTypeDescriptor = basicType.getJavaTypeDescriptor();
javaTypeDescriptor = expression.getExpressionType().getJdbcMappings().get( 0 ).getMappedJavaTypeDescriptor();
}
final SqlExpressionResolver sqlExpressionResolver = domainResultCreationState.getSqlAstCreationState().getSqlExpressionResolver();
sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression(
columnName,
state -> new SqlSelectionImpl( valuesArrayPosition, (BasicValuedMapping) basicType )
),
basicType.getJavaTypeDescriptor(),
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
expression,
javaTypeDescriptor,
sessionFactory.getTypeConfiguration()
);
// StandardRowReader expects there to be a JavaTypeDescriptor as part of the ResultAssembler.
assert javaTypeDescriptor != null;
return new BasicResult<>( valuesArrayPosition, resultAlias, javaTypeDescriptor );
return new BasicResult<>( sqlSelection.getValuesArrayPosition(), resultAlias, javaTypeDescriptor );
}
}

View File

@ -11,10 +11,13 @@ import java.util.function.BiFunction;
import org.hibernate.LockMode;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.TableGroupImpl;
import org.hibernate.sql.ast.spi.SqlAliasBaseConstant;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.entity.EntityResult;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
@ -26,7 +29,7 @@ import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
*
* @author Steve Ebersole
*/
public class DynamicResultBuilderEntityCalculated implements DynamicResultBuilderEntity {
public class DynamicResultBuilderEntityCalculated implements DynamicResultBuilderEntity, NativeQuery.RootReturn {
private final NavigablePath navigablePath;
private final EntityMappingType entityMapping;
@ -47,6 +50,51 @@ public class DynamicResultBuilderEntityCalculated implements DynamicResultBuilde
this.sessionFactory = sessionFactory;
}
@Override
public EntityMappingType getEntityMapping() {
return entityMapping;
}
@Override
public String getTableAlias() {
return tableAlias;
}
@Override
public NavigablePath getNavigablePath() {
return navigablePath;
}
@Override
public NativeQuery.RootReturn setLockMode(LockMode lockMode) {
throw new UnsupportedOperationException();
}
@Override
public NativeQuery.RootReturn addIdColumnAliases(String... aliases) {
throw new UnsupportedOperationException();
}
@Override
public String getDiscriminatorAlias() {
return null;
}
@Override
public NativeQuery.RootReturn setDiscriminatorAlias(String columnAlias) {
throw new UnsupportedOperationException();
}
@Override
public NativeQuery.RootReturn addProperty(String propertyName, String columnAlias) {
throw new UnsupportedOperationException();
}
@Override
public NativeQuery.ReturnProperty addProperty(String propertyName) {
throw new UnsupportedOperationException();
}
@Override
public EntityResult buildResult(
JdbcValuesMetadata jdbcResultsMetadata,
@ -55,11 +103,10 @@ public class DynamicResultBuilderEntityCalculated implements DynamicResultBuilde
DomainResultCreationState domainResultCreationState) {
final DomainResultCreationStateImpl creationStateImpl = ResultsHelper.impl( domainResultCreationState );
TableGroupImpl.TableReferenceImpl tableReference = new TableGroupImpl.TableReferenceImpl(
entityMapping.getEntityName(),
tableAlias,
false,
sessionFactory
final TableReference tableReference = entityMapping.createPrimaryTableReference(
new SqlAliasBaseConstant( tableAlias ),
creationStateImpl.getSqlExpressionResolver(),
creationStateImpl.getCreationContext()
);
final TableGroupImpl tableGroup = new TableGroupImpl(

View File

@ -6,23 +6,48 @@
*/
package org.hibernate.query.results.dynamic;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.FetchTiming;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.TableGroupImpl;
import org.hibernate.sql.ast.spi.FromClauseAccess;
import org.hibernate.sql.ast.spi.SqlAliasBaseConstant;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.entity.EntityResult;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
import static org.hibernate.query.results.ResultsHelper.impl;
import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey;
/**
* @author Steve Ebersole
* @author Christian Beikov
*/
public class DynamicResultBuilderEntityStandard
extends AbstractFetchBuilderContainer<DynamicResultBuilderEntityStandard>
implements DynamicResultBuilderEntity, NativeQuery.RootReturn {
private static final String ELEMENT_PREFIX = CollectionPart.Nature.ELEMENT.getName() + ".";
private final NavigablePath navigablePath;
private final EntityMappingType entityMapping;
@ -30,28 +55,51 @@ public class DynamicResultBuilderEntityStandard
private LockMode lockMode;
private List<String> idColumnNames;
private String discriminatorColumnName;
public DynamicResultBuilderEntityStandard(EntityMappingType entityMapping, String tableAlias) {
this( entityMapping, tableAlias, null );
this( entityMapping, tableAlias, new NavigablePath( entityMapping.getEntityName() ) );
}
public DynamicResultBuilderEntityStandard(
EntityMappingType entityMapping,
String tableAlias,
String discriminatorColumnName) {
this.navigablePath = new NavigablePath( entityMapping.getEntityName() );
NavigablePath navigablePath) {
this.navigablePath = navigablePath;
this.entityMapping = entityMapping;
this.tableAlias = tableAlias;
this.discriminatorColumnName = discriminatorColumnName;
}
@Override
public EntityMappingType getEntityMapping() {
return entityMapping;
}
@Override
public String getTableAlias() {
return tableAlias;
}
@Override
public NavigablePath getNavigablePath() {
return navigablePath;
}
@Override
public NativeQuery.RootReturn addIdColumnAliases(String... aliases) {
if ( idColumnNames == null ) {
idColumnNames = new ArrayList<>( aliases.length );
}
Collections.addAll( idColumnNames, aliases );
return this;
}
@Override
public String getDiscriminatorAlias() {
return discriminatorColumnName;
}
@Override
protected String getPropertyBase() {
return entityMapping.getEntityName();
@ -63,57 +111,135 @@ public class DynamicResultBuilderEntityStandard
int resultPosition,
BiFunction<String, String, DynamicFetchBuilderLegacy> legacyFetchResolver,
DomainResultCreationState domainResultCreationState) {
// final FromClauseAccessImpl fromClauseAccess = ResultsHelper.extractFromClauseAccess( domainResultCreationState );
// final TableGroup tableGroup = fromClauseAccess.resolveTableGroup(
// navigablePath,
// np -> {
// final TableGroupImpl.TableReferenceImpl tableReference = new TableGroupImpl.TableReferenceImpl(
// entityMapping.getEntityName(),
// tableAlias,
// false,
// domainResultCreationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
// );
// return new TableGroupImpl( navigablePath, tableAlias, tableReference, entityMapping, lockMode );
// }
// );
//
// return new EntityResultImpl(
// entityMapping,
// tableAlias,
// lockMode,
// jdbcResultsMetadata,
// sqlSelectionConsumer,
// () -> {
// if ( discriminatorColumnName == null ) {
// return null;
// }
//
// final int jdbcPosition;
// try {
// jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( discriminatorColumnName );
// }
// catch (Exception e) {
// return null;
// }
//
// final int valuesArrayPosition = jdbcPosition - 1;
//
// final SqlSelection discriminatorSqlSelection = new SqlSelectionImpl(
// valuesArrayPosition,
// entityMapping.getDiscriminatorMapping()
// );
//
// sqlSelectionConsumer.accept( discriminatorSqlSelection );
//
// return discriminatorSqlSelection;
// },
// // fetchableName -> fetchBuilders.get( fetchableName ),
// fetchableName -> null,
// legacyFetchResolver,
// domainResultCreationState
// );
return buildResultOrFetch(
(tableGroup) -> (EntityResult) entityMapping.createDomainResult(
navigablePath,
tableGroup,
tableAlias,
domainResultCreationState
),
jdbcResultsMetadata,
domainResultCreationState
);
}
throw new NotYetImplementedFor6Exception( getClass() );
public Fetch buildFetch(
FetchParent parent,
Fetchable fetchable,
JdbcValuesMetadata jdbcResultsMetadata,
DomainResultCreationState domainResultCreationState) {
return buildResultOrFetch(
(tableGroup) -> parent.generateFetchableFetch(
fetchable,
navigablePath,
FetchTiming.IMMEDIATE,
true,
lockMode,
null,
domainResultCreationState
),
jdbcResultsMetadata,
domainResultCreationState
);
}
private <T> T buildResultOrFetch(
Function<TableGroup, T> resultOrFetchBuilder,
JdbcValuesMetadata jdbcResultsMetadata,
DomainResultCreationState domainResultCreationState) {
final DomainResultCreationStateImpl creationState = impl( domainResultCreationState );
final FromClauseAccess fromClauseAccess = domainResultCreationState.getSqlAstCreationState().getFromClauseAccess();
final TableGroup tableGroup = fromClauseAccess.resolveTableGroup(
navigablePath,
np -> {
final TableReference tableReference = entityMapping.createPrimaryTableReference(
new SqlAliasBaseConstant( tableAlias ),
creationState.getSqlExpressionResolver(),
creationState.getCreationContext()
);
return new TableGroupImpl( navigablePath, tableAlias, tableReference, entityMapping, lockMode );
}
);
final TableReference tableReference = tableGroup.getPrimaryTableReference();
if ( idColumnNames != null ) {
final EntityIdentifierMapping identifierMapping = entityMapping.getIdentifierMapping();
identifierMapping.forEachSelectable(
(selectionIndex, selectableMapping) -> {
resolveSqlSelection(
idColumnNames.get( selectionIndex ),
createColumnReferenceKey( tableReference, selectableMapping.getSelectionExpression() ),
selectableMapping.getJdbcMapping(),
jdbcResultsMetadata,
domainResultCreationState
);
}
);
}
if ( discriminatorColumnName != null ) {
resolveSqlSelection(
discriminatorColumnName,
createColumnReferenceKey(
tableReference,
entityMapping.getDiscriminatorMapping().getSelectionExpression()
),
entityMapping.getDiscriminatorMapping().getJdbcMapping(),
jdbcResultsMetadata,
domainResultCreationState
);
}
try {
final NavigablePath currentRelativePath = creationState.getCurrentRelativePath();
final String prefix;
if ( currentRelativePath == null ) {
prefix = "";
}
else {
prefix = currentRelativePath.getFullPath() + ".";
}
creationState.pushExplicitFetchMementoResolver(
relativePath -> {
if ( relativePath.startsWith( prefix ) ) {
final int startIndex;
if ( relativePath.regionMatches( prefix.length(), ELEMENT_PREFIX, 0, ELEMENT_PREFIX.length() ) ) {
startIndex = prefix.length() + ELEMENT_PREFIX.length();
}
else {
startIndex = prefix.length();
}
return findFetchBuilder( relativePath.substring( startIndex ) );
}
return null;
}
);
return resultOrFetchBuilder.apply( tableGroup );
}
finally {
creationState.popExplicitFetchMementoResolver();
}
}
private void resolveSqlSelection(
String columnAlias,
String columnKey,
JdbcMapping jdbcMapping,
JdbcValuesMetadata jdbcResultsMetadata,
DomainResultCreationState domainResultCreationState) {
final SqlExpressionResolver sqlExpressionResolver = domainResultCreationState.getSqlAstCreationState().getSqlExpressionResolver();
sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression(
columnKey,
state -> {
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
final int valuesArrayPosition = jdbcPosition - 1;
return new SqlSelectionImpl( valuesArrayPosition, jdbcMapping );
}
),
jdbcMapping.getMappedJavaTypeDescriptor(),
domainResultCreationState.getSqlAstCreationState().getCreationContext().getSessionFactory().getTypeConfiguration()
);
}
@Override

View File

@ -17,6 +17,7 @@ import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.ResultsHelper;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.DomainResultCreationState;
@ -55,15 +56,16 @@ public class ImplicitFetchBuilderBasic implements ImplicitFetchBuilder {
final String column = fetchable.getSelectionExpression();
final String table = fetchable.getContainingTableExpression();
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( column );
final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition );
final Expression expression = creationStateImpl.resolveSqlExpression(
createColumnReferenceKey( parentTableGroup.getTableReference( fetchPath, table ), column ),
processingState -> new SqlSelectionImpl( valuesArrayPosition, fetchable )
processingState -> {
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( column );
final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition );
return new SqlSelectionImpl( valuesArrayPosition, fetchable );
}
);
creationStateImpl.resolveSqlSelection(
final SqlSelection sqlSelection = creationStateImpl.resolveSqlSelection(
expression,
fetchable.getJavaTypeDescriptor(),
domainResultCreationState.getSqlAstCreationState()
@ -81,7 +83,7 @@ public class ImplicitFetchBuilderBasic implements ImplicitFetchBuilder {
}
return new BasicFetch<>(
valuesArrayPosition,
sqlSelection.getValuesArrayPosition(),
parent,
fetchPath,
fetchable,

View File

@ -18,6 +18,7 @@ import org.hibernate.internal.EmptyScrollableResults;
import org.hibernate.metamodel.mapping.BasicValuedMapping;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.query.results.ResultSetMapping;
import org.hibernate.query.spi.QueryParameterBinding;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.spi.QueryParameterImplementor;
@ -53,12 +54,14 @@ public class NativeSelectQueryPlanImpl<R> implements NativeSelectQueryPlan<R> {
String sql,
Set<String> affectedTableNames,
List<QueryParameterImplementor<?>> parameterList,
JdbcValuesMappingProducer resultSetMapping,
ResultSetMapping resultSetMapping,
RowTransformer<R> rowTransformer,
SessionFactoryImplementor sessionFactory) {
this.sql = sql;
final ResultSetMappingProcessor processor = new ResultSetMappingProcessor( resultSetMapping, sessionFactory );
final SQLQueryParser parser = new SQLQueryParser( sql, processor.process(), sessionFactory );
this.sql = parser.process();
this.parameterList = parameterList;
this.resultSetMapping = resultSetMapping;
this.resultSetMapping = processor.generateResultMapping( parser.queryHasAliases() );
this.rowTransformer = rowTransformer != null
? rowTransformer
: RowTransformerPassThruImpl.instance();

View File

@ -0,0 +1,466 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.query.sql.internal;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.loader.internal.AliasConstantsHelper;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.SQLLoadableCollection;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.entity.SQLLoadable;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.ResultSetMapping;
import org.hibernate.query.results.ResultSetMappingImpl;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.query.results.dynamic.DynamicResultBuilderEntityStandard;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
/**
* Responsible for processing the {@link ResultSetMapping}
* defined by a {@link org.hibernate.query.sql.spi.NativeSelectQueryDefinition} and
* pre-process it for consumption in {@link SQLQueryParser}.
*
* @author Gavin King
* @author Max Andersen
* @author Steve Ebersole
*/
public class ResultSetMappingProcessor implements SQLQueryParser.ParserContext {
private static final CoreMessageLogger LOG = CoreLogging.messageLogger( ResultSetMappingProcessor.class );
private final ResultSetMapping resultSetMapping;
private final Map<String, NativeQuery.ResultNode> alias2Return = new HashMap<>();
private final Map<String, String> alias2OwnerAlias = new HashMap<>();
private final Map<String, EntityPersister> alias2Persister = new HashMap<>();
private final Map<String, String> alias2Suffix = new HashMap<>();
private final Map<String, CollectionPersister> alias2CollectionPersister = new HashMap<>();
private final Map<String, String> alias2CollectionSuffix = new HashMap<>();
private final Map<String, Map<String, String[]>> entityPropertyResultMaps = new HashMap<>();
private final Map<String, Map<String, String[]>> collectionPropertyResultMaps = new HashMap<>();
private final SessionFactoryImplementor factory;
private int entitySuffixSeed;
private int collectionSuffixSeed;
public ResultSetMappingProcessor(ResultSetMapping resultSetMapping, SessionFactoryImplementor factory) {
this.resultSetMapping = resultSetMapping;
this.factory = factory;
}
private Map<String, String[]> internalGetPropertyResultsMap(String alias) {
Map<String, String[]> propertyResultMaps = collectionPropertyResultMaps.get( alias );
if ( propertyResultMaps == null ) {
propertyResultMaps = entityPropertyResultMaps.get( alias );
}
if ( propertyResultMaps != null ) {
return propertyResultMaps;
}
NativeQuery.ResultNode rtn = alias2Return.get( alias );
if ( rtn instanceof NativeQuery.ReturnProperty && !( rtn instanceof NativeQuery.FetchReturn ) ) {
return null;
}
else {
// todo (6.0): access property results map somehow which was on NativeSQLQueryNonScalarReturn before
return Collections.emptyMap();
}
}
private boolean hasPropertyResultMap(String alias) {
Map<String, String[]> propertyMaps = internalGetPropertyResultsMap( alias );
return propertyMaps != null && ! propertyMaps.isEmpty();
}
public SQLQueryParser.ParserContext process() {
// first, break down the returns into maps keyed by alias
// so that role returns can be more easily resolved to their owners
resultSetMapping.visitResultBuilders(
(i, resultBuilder) -> {
if ( resultBuilder instanceof NativeQuery.RootReturn ) {
final NativeQuery.RootReturn rootReturn = (NativeQuery.RootReturn) resultBuilder;
alias2Return.put( rootReturn.getTableAlias(), rootReturn );
}
}
);
resultSetMapping.visitLegacyFetchBuilders(
fetchBuilder -> {
alias2Return.put( fetchBuilder.getTableAlias(), fetchBuilder );
alias2OwnerAlias.put( fetchBuilder.getTableAlias(), fetchBuilder.getOwnerAlias() );
}
);
// Now, process the returns
for ( NativeQuery.ResultNode queryReturn : alias2Return.values() ) {
processReturn( queryReturn );
}
return this;
}
public ResultSetMapping generateResultMapping(boolean queryHadAliases) {
if ( !queryHadAliases ) {
return this.resultSetMapping;
}
final ResultSetMappingImpl resultSetMapping = new ResultSetMappingImpl( null );
final Set<String> visited = new HashSet<>();
this.resultSetMapping.visitResultBuilders(
(i, resultBuilder) -> {
if ( resultBuilder instanceof NativeQuery.RootReturn ) {
final NativeQuery.RootReturn rootReturn = (NativeQuery.RootReturn) resultBuilder;
final String suffix = alias2Suffix.get( rootReturn.getTableAlias() );
visited.add( rootReturn.getTableAlias() );
if ( suffix == null ) {
resultSetMapping.addResultBuilder( resultBuilder );
}
else {
final DynamicResultBuilderEntityStandard resultBuilderEntity = createSuffixedResultBuilder(
rootReturn,
suffix
);
resultSetMapping.addResultBuilder( resultBuilderEntity );
alias2Return.put( rootReturn.getTableAlias(), resultBuilderEntity );
}
}
else {
resultSetMapping.addResultBuilder( resultBuilder );
}
}
);
this.resultSetMapping.visitLegacyFetchBuilders(
fetchBuilder -> applyFetchBuilder( resultSetMapping, fetchBuilder, visited )
);
return resultSetMapping;
}
private void applyFetchBuilder(
ResultSetMappingImpl resultSetMapping,
DynamicFetchBuilderLegacy fetchBuilder,
Set<String> visited) {
if ( !visited.add( fetchBuilder.getTableAlias() ) ) {
return;
}
final String suffix = alias2Suffix.get( fetchBuilder.getTableAlias() );
if ( suffix == null ) {
resultSetMapping.addLegacyFetchBuilder( fetchBuilder );
}
else {
if ( !visited.contains( fetchBuilder.getOwnerAlias() ) ) {
applyFetchBuilder(
resultSetMapping,
// At this point, only legacy fetch builders weren't visited
(DynamicFetchBuilderLegacy) alias2Return.get( fetchBuilder.getOwnerAlias() ),
visited
);
}
// At this point, the owner builder must be a DynamicResultBuilderEntityStandard to which we can add this builder to
final DynamicResultBuilderEntityStandard ownerBuilder = (DynamicResultBuilderEntityStandard) alias2Return.get(
fetchBuilder.getOwnerAlias()
);
final DynamicResultBuilderEntityStandard resultBuilderEntity = createSuffixedResultBuilder(
alias2Persister.get( fetchBuilder.getTableAlias() ).findContainingEntityMapping(),
fetchBuilder.getTableAlias(),
suffix,
determineNavigablePath( fetchBuilder )
);
final SQLLoadable loadable = (SQLLoadable) alias2Persister.get( fetchBuilder.getOwnerAlias() );
final List<String> columnNames;
final String[] columnAliases = loadable.getSubclassPropertyColumnAliases(
fetchBuilder.getFetchableName(),
suffix
);
if ( columnAliases.length == 0 ) {
final CollectionPersister collectionPersister = alias2CollectionPersister.get( fetchBuilder.getTableAlias() );
if ( collectionPersister == null ) {
columnNames = Collections.emptyList();
}
else {
columnNames = Arrays.asList( collectionPersister.getKeyColumnAliases( suffix ) );
}
}
else {
columnNames = Arrays.asList( columnAliases );
}
ownerBuilder.addFetchBuilder(
fetchBuilder.getFetchableName(),
new DynamicFetchBuilderLegacy(
fetchBuilder.getTableAlias(),
fetchBuilder.getOwnerAlias(),
fetchBuilder.getFetchableName(),
columnNames,
resultBuilderEntity
)
);
// resultSetMapping.addResultBuilder( resultBuilderEntity );
alias2Return.put( fetchBuilder.getTableAlias(), resultBuilderEntity );
}
}
private NavigablePath determineNavigablePath(DynamicFetchBuilderLegacy fetchBuilder) {
final NativeQuery.ResultNode ownerResult = alias2Return.get( fetchBuilder.getOwnerAlias() );
if ( ownerResult instanceof NativeQuery.RootReturn ) {
return ( (NativeQuery.RootReturn) ownerResult ).getNavigablePath()
.append( fetchBuilder.getFetchableName() );
}
else {
return determineNavigablePath( ( DynamicFetchBuilderLegacy) ownerResult )
.append( fetchBuilder.getFetchableName() );
}
}
private DynamicResultBuilderEntityStandard createSuffixedResultBuilder(
NativeQuery.RootReturn rootReturn,
String suffix) {
return createSuffixedResultBuilder(
rootReturn.getEntityMapping(),
rootReturn.getTableAlias(),
suffix,
new NavigablePath( rootReturn.getEntityMapping().getEntityName() )
);
}
private DynamicResultBuilderEntityStandard createSuffixedResultBuilder(
EntityMappingType entityMapping,
String tableAlias,
String suffix,
NavigablePath navigablePath) {
final SQLLoadable loadable = (SQLLoadable) entityMapping.getEntityPersister();
final DynamicResultBuilderEntityStandard resultBuilderEntity = new DynamicResultBuilderEntityStandard(
entityMapping,
tableAlias,
navigablePath
);
resultBuilderEntity.addIdColumnAliases( loadable.getIdentifierAliases( suffix ) );
resultBuilderEntity.setDiscriminatorAlias( loadable.getDiscriminatorAlias( suffix ) );
for ( String propertyName : loadable.getPropertyNames() ) {
final String[] columnAliases = loadable.getSubclassPropertyColumnAliases(
propertyName,
suffix
);
if ( columnAliases.length != 0 ) {
resultBuilderEntity.addProperty(
propertyName,
columnAliases
);
}
}
return resultBuilderEntity;
}
private SQLLoadable getSQLLoadable(String entityName) throws MappingException {
EntityPersister persister = factory.getEntityPersister( entityName );
if ( !(persister instanceof SQLLoadable) ) {
throw new MappingException( "class persister is not SQLLoadable: " + entityName );
}
return (SQLLoadable) persister;
}
private String generateEntitySuffix() {
return AliasConstantsHelper.get( entitySuffixSeed++ );
}
private String generateCollectionSuffix() {
return collectionSuffixSeed++ + "__";
}
private void processReturn(NativeQuery.ResultNode rtn) {
if ( rtn instanceof NativeQuery.RootReturn ) {
processRootReturn( ( NativeQuery.RootReturn ) rtn );
}
else if ( rtn instanceof NativeQuery.FetchReturn ) {
processFetchReturn( (NativeQuery.FetchReturn) rtn );
}
else if ( rtn instanceof NativeQuery.InstantiationResultNode<?> ) {
processConstructorReturn( (NativeQuery.InstantiationResultNode<?>) rtn );
}
else if ( rtn instanceof NativeQuery.ReturnProperty ) {
processScalarReturn( ( NativeQuery.ReturnProperty ) rtn );
}
else if ( rtn instanceof NativeQuery.ReturnableResultNode ) {
}
else {
throw new IllegalStateException(
"Unrecognized NativeSQLQueryReturn concrete type encountered : " + rtn
);
}
}
private void processConstructorReturn(NativeQuery.InstantiationResultNode<?> rtn) {
}
private void processScalarReturn(NativeQuery.ReturnProperty typeReturn) {
// scalarColumnAliases.add( typeReturn.getColumnAlias() );
// scalarTypes.add( typeReturn.getType() );
}
private void processRootReturn(NativeQuery.RootReturn rootReturn) {
if ( alias2Persister.containsKey( rootReturn.getTableAlias() ) ) {
// already been processed...
return;
}
SQLLoadable persister = (SQLLoadable) rootReturn.getEntityMapping().getEntityPersister();
Map<String, String[]> propertyResultsMap = Collections.emptyMap();//rootReturn.getPropertyResultsMap()
addPersister( rootReturn.getTableAlias(), propertyResultsMap, persister );
}
private void addPersister(String alias, Map<String, String[]> propertyResult, SQLLoadable persister) {
alias2Persister.put( alias, persister );
String suffix = generateEntitySuffix();
LOG.tracev( "Mapping alias [{0}] to entity-suffix [{1}]", alias, suffix );
alias2Suffix.put( alias, suffix );
entityPropertyResultMaps.put( alias, propertyResult );
}
private void addCollection(String role, String alias, Map<String, String[]> propertyResults) {
SQLLoadableCollection collectionPersister = ( SQLLoadableCollection ) factory.getCollectionPersister( role );
alias2CollectionPersister.put( alias, collectionPersister );
String suffix = generateCollectionSuffix();
LOG.tracev( "Mapping alias [{0}] to collection-suffix [{1}]", alias, suffix );
alias2CollectionSuffix.put( alias, suffix );
collectionPropertyResultMaps.put( alias, propertyResults );
if ( collectionPersister.isOneToMany() || collectionPersister.isManyToMany() ) {
SQLLoadable persister = ( SQLLoadable ) collectionPersister.getElementPersister();
addPersister( alias, filter( propertyResults ), persister );
}
}
private Map<String, String[]> filter(Map<String, String[]> propertyResults) {
final Map<String, String[]> result = new HashMap<>( propertyResults.size() );
final String keyPrefix = "element.";
for ( Map.Entry<String, String[]> element : propertyResults.entrySet() ) {
final String path = element.getKey();
if ( path.startsWith( keyPrefix ) ) {
result.put( path.substring( keyPrefix.length() ), element.getValue() );
}
}
return result;
}
private void processFetchReturn(NativeQuery.FetchReturn fetchReturn) {
String alias = fetchReturn.getTableAlias();
if ( alias2Persister.containsKey( alias ) || alias2CollectionPersister.containsKey( alias ) ) {
// already been processed...
return;
}
String ownerAlias = fetchReturn.getOwnerAlias();
// Make sure the owner alias is known...
if ( !alias2Return.containsKey( ownerAlias ) ) {
throw new HibernateException( "Owner alias [" + ownerAlias + "] is unknown for alias [" + alias + "]" );
}
// If this return's alias has not been processed yet, do so before further processing of this return
if ( !alias2Persister.containsKey( ownerAlias ) ) {
processReturn( alias2Return.get(ownerAlias) );
}
SQLLoadable ownerPersister = ( SQLLoadable ) alias2Persister.get( ownerAlias );
Type returnType = ownerPersister.getPropertyType( fetchReturn.getFetchableName() );
if ( returnType.isCollectionType() ) {
String role = ownerPersister.getEntityName() + '.' + fetchReturn.getFetchableName();
Map<String, String[]> propertyResultsMap = Collections.emptyMap();//fetchReturn.getPropertyResultsMap()
addCollection( role, alias, propertyResultsMap );
// collectionOwnerAliases.add( ownerAlias );
}
else if ( returnType.isEntityType() ) {
EntityType eType = ( EntityType ) returnType;
String returnEntityName = eType.getAssociatedEntityName();
SQLLoadable persister = getSQLLoadable( returnEntityName );
Map<String, String[]> propertyResultsMap = Collections.emptyMap();//fetchReturn.getPropertyResultsMap()
addPersister( alias, propertyResultsMap, persister );
}
}
@Override
public boolean isEntityAlias(String alias) {
return this.getEntityPersister( alias ) != null;
}
@Override
public boolean isCollectionAlias(String alias) {
return this.getCollectionPersister( alias ) != null;
}
@Override
public SQLLoadable getEntityPersister(String alias) {
return (SQLLoadable) alias2Persister.get( alias );
}
@Override
public SQLLoadableCollection getCollectionPersister(String alias) {
return (SQLLoadableCollection) alias2CollectionPersister.get( alias );
}
@Override
public String getEntitySuffix(String alias) {
return alias2Suffix.get( alias );
}
@Override
public String getCollectionSuffix(String alias) {
return alias2CollectionSuffix.get( alias );
}
public String getOwnerAlias(String alias) {
return alias2OwnerAlias.get( alias );
}
@Override
public Map<String, String[]> getPropertyResultsMap(String alias) {
return internalGetPropertyResultsMap( alias );
}
public String[] collectQuerySpaces() {
final HashSet<String> spaces = new HashSet<String>();
collectQuerySpaces( spaces );
return spaces.toArray( new String[ spaces.size() ] );
}
public void collectQuerySpaces(Collection<String> spaces) {
for ( EntityPersister persister : alias2Persister.values() ) {
Collections.addAll( spaces, (String[]) persister.getQuerySpaces() );
}
for ( CollectionPersister persister : alias2CollectionPersister.values() ) {
final Type elementType = persister.getElementType();
if ( elementType.isEntityType() && ! elementType.isAnyType() ) {
final Joinable joinable = ( (EntityType) elementType ).getAssociatedJoinable( factory );
Collections.addAll( spaces, (String[]) ( (EntityPersister) joinable ).getQuerySpaces() );
}
}
}
}

View File

@ -33,14 +33,14 @@ public class SQLQueryParser {
private long aliasesFound;
interface ParserContext {
public interface ParserContext {
boolean isEntityAlias(String aliasName);
SQLLoadable getEntityPersisterByAlias(String alias);
String getEntitySuffixByAlias(String alias);
SQLLoadable getEntityPersister(String alias);
String getEntitySuffix(String alias);
boolean isCollectionAlias(String aliasName);
SQLLoadableCollection getCollectionPersisterByAlias(String alias);
String getCollectionSuffixByAlias(String alias);
Map getPropertyResultsMapByAlias(String alias);
SQLLoadableCollection getCollectionPersister(String alias);
String getCollectionSuffix(String alias);
Map<String, String[]> getPropertyResultsMap(String alias);
}
public SQLQueryParser(String queryString, ParserContext context, SessionFactoryImplementor factory) {
@ -64,12 +64,11 @@ public class SQLQueryParser {
// TODO: should "record" how many properties we have referred to - and if we
// don't get them all we throw an exception! Way better than trial and error ;)
protected String substituteBrackets(String sqlQuery) throws QueryException {
if ( PREPARED_STATEMENT_PATTERN.matcher( sqlQuery.trim() ).matches() ) {
return sqlQuery;
}
StringBuilder result = new StringBuilder( sqlQuery.length() + 20 );
final StringBuilder result = new StringBuilder( sqlQuery.length() + 20 );
int left, right;
// replace {....} with corresponding column aliases
@ -82,7 +81,7 @@ public class SQLQueryParser {
}
// append everything up until the next encountered open brace
result.append( sqlQuery.substring( curr, left ) );
result.append( sqlQuery, curr, left );
if ( ( right = sqlQuery.indexOf( '}', left + 1 ) ) < 0 ) {
throw new QueryException( "Unmatched braces for alias path", sqlQuery );
@ -93,39 +92,43 @@ public class SQLQueryParser {
if ( isPlaceholder ) {
// Domain replacement
if ( DOMAIN_PLACEHOLDER.equals( aliasPath ) ) {
final String catalogName = factory.getSettings().getDefaultCatalogName();
if ( catalogName != null ) {
result.append( catalogName );
result.append( "." );
switch ( aliasPath ) {
case DOMAIN_PLACEHOLDER: {
final String catalogName = factory.getSettings().getDefaultCatalogName();
if ( catalogName != null ) {
result.append( catalogName );
result.append( "." );
}
final String schemaName = factory.getSettings().getDefaultSchemaName();
if ( schemaName != null ) {
result.append( schemaName );
result.append( "." );
}
break;
}
final String schemaName = factory.getSettings().getDefaultSchemaName();
if ( schemaName != null ) {
result.append( schemaName );
result.append( "." );
// Schema replacement
case SCHEMA_PLACEHOLDER: {
final String schemaName = factory.getSettings().getDefaultSchemaName();
if ( schemaName != null ) {
result.append( schemaName );
result.append( "." );
}
break;
}
}
// Schema replacement
else if ( SCHEMA_PLACEHOLDER.equals( aliasPath ) ) {
final String schemaName = factory.getSettings().getDefaultSchemaName();
if ( schemaName != null ) {
result.append(schemaName);
result.append(".");
// Catalog replacement
case CATALOG_PLACEHOLDER: {
final String catalogName = factory.getSettings().getDefaultCatalogName();
if ( catalogName != null ) {
result.append( catalogName );
result.append( "." );
}
break;
}
}
// Catalog replacement
else if ( CATALOG_PLACEHOLDER.equals( aliasPath ) ) {
final String catalogName = factory.getSettings().getDefaultCatalogName();
if ( catalogName != null ) {
result.append( catalogName );
result.append( "." );
}
}
else {
throw new QueryException( "Unknown placeholder ", aliasPath );
default:
throw new QueryException( "Unknown placeholder ", aliasPath );
}
}
else if (context != null) {
else if ( context != null ) {
int firstDot = aliasPath.indexOf( '.' );
if ( firstDot == -1 ) {
if ( context.isEntityAlias( aliasPath ) ) {
@ -135,7 +138,7 @@ public class SQLQueryParser {
}
else {
// passing through anything we do not know : to support jdbc escape sequences HB-898
result.append( '{' ).append(aliasPath).append( '}' );
result.append( '{' ).append( aliasPath ).append( '}' );
}
}
else {
@ -154,12 +157,12 @@ public class SQLQueryParser {
}
else {
// passing through anything we do not know : to support jdbc escape sequences HB-898
result.append( '{' ).append(aliasPath).append( '}' );
result.append( '{' ).append( aliasPath ).append( '}' );
}
}
}
else {
result.append( '{' ).append(aliasPath).append( '}' );
result.append( '{' ).append( aliasPath ).append( '}' );
}
}
@ -171,71 +174,71 @@ public class SQLQueryParser {
private String resolveCollectionProperties(
String aliasName,
String propertyName) {
final Map<String, String[]> fieldResults = context.getPropertyResultsMap( aliasName );
final SQLLoadableCollection collectionPersister = context.getCollectionPersister( aliasName );
final String collectionSuffix = context.getCollectionSuffix( aliasName );
Map fieldResults = context.getPropertyResultsMapByAlias( aliasName );
SQLLoadableCollection collectionPersister = context.getCollectionPersisterByAlias( aliasName );
String collectionSuffix = context.getCollectionSuffixByAlias( aliasName );
switch ( propertyName ) {
case "*":
if ( !fieldResults.isEmpty() ) {
throw new QueryException( "Using return-propertys together with * syntax is not supported." );
}
if ( "*".equals( propertyName ) ) {
if( !fieldResults.isEmpty() ) {
throw new QueryException("Using return-propertys together with * syntax is not supported.");
}
String selectFragment = collectionPersister.selectFragment( aliasName, collectionSuffix );
aliasesFound++;
return selectFragment
String selectFragment = collectionPersister.selectFragment( aliasName, collectionSuffix );
aliasesFound++;
return selectFragment
+ ", "
+ resolveProperties( aliasName, propertyName );
}
else if ( "element.*".equals( propertyName ) ) {
return resolveProperties( aliasName, "*" );
}
else {
String[] columnAliases;
case "element.*":
return resolveProperties( aliasName, "*" );
default: {
String[] columnAliases;
// Let return-properties override whatever the persister has for aliases.
columnAliases = ( String[] ) fieldResults.get(propertyName);
if ( columnAliases==null ) {
columnAliases = collectionPersister.getCollectionPropertyColumnAliases( propertyName, collectionSuffix );
}
// Let return-properties override whatever the persister has for aliases.
columnAliases = fieldResults.get( propertyName );
if ( columnAliases == null ) {
columnAliases = collectionPersister.getCollectionPropertyColumnAliases(
propertyName,
collectionSuffix
);
}
if ( columnAliases == null || columnAliases.length == 0 ) {
throw new QueryException(
"No column name found for property [" + propertyName + "] for alias [" + aliasName + "]",
originalQueryString
);
if ( columnAliases == null || columnAliases.length == 0 ) {
throw new QueryException(
"No column name found for property [" + propertyName + "] for alias [" + aliasName + "]",
originalQueryString
);
}
if ( columnAliases.length != 1 ) {
// TODO: better error message since we actually support composites if names are explicitly listed.
throw new QueryException(
"SQL queries only support properties mapped to a single column - property [" +
propertyName + "] is mapped to " + columnAliases.length + " columns.",
originalQueryString
);
}
aliasesFound++;
return columnAliases[0];
}
if ( columnAliases.length != 1 ) {
// TODO: better error message since we actually support composites if names are explicitly listed.
throw new QueryException(
"SQL queries only support properties mapped to a single column - property [" +
propertyName + "] is mapped to " + columnAliases.length + " columns.",
originalQueryString
);
}
aliasesFound++;
return columnAliases[0];
}
}
private String resolveProperties(String aliasName, String propertyName) {
Map fieldResults = context.getPropertyResultsMapByAlias( aliasName );
SQLLoadable persister = context.getEntityPersisterByAlias( aliasName );
String suffix = context.getEntitySuffixByAlias( aliasName );
final Map<String, String[]> fieldResults = context.getPropertyResultsMap( aliasName );
final SQLLoadable persister = context.getEntityPersister( aliasName );
final String suffix = context.getEntitySuffix( aliasName );
if ( "*".equals( propertyName ) ) {
if( !fieldResults.isEmpty() ) {
throw new QueryException("Using return-propertys together with * syntax is not supported.");
throw new QueryException( "Using return-propertys together with * syntax is not supported." );
}
aliasesFound++;
return persister.selectFragment( aliasName, suffix ) ;
}
else {
String[] columnAliases;
// Let return-propertiess override whatever the persister has for aliases.
columnAliases = (String[]) fieldResults.get( propertyName );
columnAliases = fieldResults.get( propertyName );
if ( columnAliases == null ) {
columnAliases = persister.getSubclassPropertyColumnAliases( propertyName, suffix );
}

View File

@ -82,8 +82,7 @@ public class MatchingIdSelectionHelper {
final TableGroup mutatingTableGroup = sqmConverter.getMutatingTableGroup();
idSelectionQuery.getFromClause().addRoot( mutatingTableGroup );
//noinspection rawtypes
final List<DomainResult> domainResults = new ArrayList<>();
final List<DomainResult<?>> domainResults = new ArrayList<>();
targetEntityDescriptor.getIdentifierMapping().forEachSelectable(
(position, selection) -> {

View File

@ -141,7 +141,7 @@ public abstract class AbstractCteMutationHandler extends AbstractMutationHandler
// Create the main query spec that will return the count of
final QuerySpec querySpec = new QuerySpec( true, 1 );
final List<DomainResult> domainResults = new ArrayList<>( 1 );
final List<DomainResult<?>> domainResults = new ArrayList<>( 1 );
final SelectStatement statement = new SelectStatement( querySpec, domainResults );
final JdbcServices jdbcServices = factory.getJdbcServices();
final SqlAstTranslator<JdbcSelect> translator = jdbcServices.getJdbcEnvironment()

View File

@ -77,11 +77,6 @@ public class TableBasedDeleteHandler
}
private ExecutionDelegate resolveDelegate(ExecutionContext executionContext) {
if ( ( getSqmDeleteOrUpdateStatement().getWhereClause() == null || getSqmDeleteOrUpdateStatement().getWhereClause().getPredicate() == null )
&& ! getEntityDescriptor().isAffectedByEnabledFilters( executionContext.getLoadQueryInfluencers() ) ) {
return new UnrestrictedDeleteExecutionDelegate( getEntityDescriptor() );
}
return new RestrictedDeleteExecutionDelegate(
getEntityDescriptor(),
idTable,

View File

@ -1,102 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.query.sqm.mutation.internal.idtable;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.MutableInteger;
import org.hibernate.internal.FilterHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.entity.JoinedSubclassEntityPersister;
import org.hibernate.query.spi.SqlOmittingQueryOptions;
import org.hibernate.query.sqm.mutation.internal.SqmMutationStrategyHelper;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl;
import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.exec.spi.JdbcDelete;
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
/**
* @author Steve Ebersole
*/
public class UnrestrictedDeleteExecutionDelegate implements TableBasedDeleteHandler.ExecutionDelegate {
private final EntityMappingType entityDescriptor;
public UnrestrictedDeleteExecutionDelegate(EntityMappingType entityDescriptor) {
this.entityDescriptor = entityDescriptor;
}
@Override
public int execute(ExecutionContext executionContext) {
// NOTE : we want the number of rows returned from this method to be the number of rows deleted
// from the root table of the entity hierarchy, which happens to be the last table we
// will visit
final MutableInteger result = new MutableInteger();
SqmMutationStrategyHelper.cleanUpCollectionTables(
entityDescriptor,
(tableReference, attributeMapping) -> null,
JdbcParameterBindings.NO_BINDINGS,
executionContext
);
entityDescriptor.visitConstraintOrderedTables(
(tableExpression, tableKeyColumnsVisitationSupplier) -> {
final int rows = deleteFrom( tableExpression, executionContext );
result.set( rows );
}
);
return result.get();
}
private int deleteFrom(
String tableExpression,
ExecutionContext executionContext) {
final SessionFactoryImplementor factory = executionContext.getSession().getFactory();
Predicate predicate = null;
if ( ! (entityDescriptor instanceof JoinedSubclassEntityPersister) ||
tableExpression.equals( ( (JoinedSubclassEntityPersister) entityDescriptor ).getTableName() ) ) {
predicate = FilterHelper.createFilterPredicate(
executionContext.getLoadQueryInfluencers(),
(Joinable) entityDescriptor
);
}
final DeleteStatement deleteStatement = new DeleteStatement(
new TableReference( tableExpression, null, true, factory ),
predicate
);
final JdbcServices jdbcServices = factory.getJdbcServices();
final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment();
final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( 1 );
final SqlAstTranslatorFactory sqlAstTranslatorFactory = jdbcEnvironment.getSqlAstTranslatorFactory();
final JdbcDelete jdbcDelete = sqlAstTranslatorFactory.buildDeleteTranslator( factory, deleteStatement )
.translate( jdbcParameterBindings, executionContext.getQueryOptions() );
return jdbcServices.getJdbcMutationExecutor().execute(
jdbcDelete,
jdbcParameterBindings,
sql -> executionContext.getSession()
.getJdbcCoordinator()
.getStatementPreparer()
.prepareStatement( sql ),
(integer, preparedStatement) -> {},
SqlOmittingQueryOptions.omitSqlQueryOptions( executionContext )
);
}
}

View File

@ -210,6 +210,7 @@ import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.sql.ast.SqlTreeCreationException;
import org.hibernate.sql.ast.SqlTreeCreationLogger;
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
import org.hibernate.sql.ast.spi.FromClauseAccess;
import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
@ -333,7 +334,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
private final QueryParameterBindings domainParameterBindings;
private final Map<SqmParameter,MappingModelExpressable> sqmParameterMappingModelTypes = new LinkedHashMap<>();
private final Map<JpaCriteriaParameter<?>, Supplier<SqmJpaCriteriaParameterWrapper<?>>> jpaCriteriaParamResolutions;
private final List<DomainResult> domainResults;
private final List<DomainResult<?>> domainResults;
private final EntityGraphTraversalState entityGraphTraversalState;
private int fetchDepth;
@ -589,7 +590,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
rootPath,
sqmStatement.getRoot().getAlias(),
LockMode.WRITE,
() -> predicate -> additionalRestrictions = predicate,
() -> predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates( additionalRestrictions, predicate ),
this,
getCreationContext()
);
@ -615,7 +616,10 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final FilterPredicate filterPredicate = FilterHelper.createFilterPredicate(
getLoadQueryInfluencers(),
(Joinable) entityDescriptor
(Joinable) entityDescriptor,
rootTableGroup,
// todo (6.0): this is temporary until we implement proper alias support
AbstractSqlAstTranslator.rendersTableReferenceAlias( Clause.UPDATE )
);
if ( filterPredicate != null ) {
additionalRestrictions = SqlAstTreeHelper.combinePredicates( additionalRestrictions, filterPredicate );
@ -844,7 +848,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
rootPath,
statement.getRoot().getAlias(),
LockMode.WRITE,
() -> predicate -> additionalRestrictions = predicate,
() -> predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates( additionalRestrictions, predicate ),
this,
getCreationContext()
);
@ -856,7 +860,10 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final FilterPredicate filterPredicate = FilterHelper.createFilterPredicate(
getLoadQueryInfluencers(),
(Joinable) entityDescriptor
(Joinable) entityDescriptor,
rootTableGroup,
// todo (6.0): this is temporary until we implement proper alias support
AbstractSqlAstTranslator.rendersTableReferenceAlias( Clause.DELETE )
);
if ( filterPredicate != null ) {
additionalRestrictions = SqlAstTreeHelper.combinePredicates( additionalRestrictions, filterPredicate );
@ -924,7 +931,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
rootPath,
sqmStatement.getTarget().getExplicitAlias(),
LockMode.WRITE,
() -> predicate -> additionalRestrictions = predicate,
() -> predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates( additionalRestrictions, predicate ),
this,
getCreationContext()
);
@ -1023,7 +1030,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
rootPath,
sqmStatement.getTarget().getExplicitAlias(),
LockMode.WRITE,
() -> predicate -> additionalRestrictions = predicate,
() -> predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates( additionalRestrictions, predicate ),
this,
getCreationContext()
);

View File

@ -2657,13 +2657,9 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
protected void renderTableReference(TableReference tableReference) {
appendSql( tableReference.getTableExpression() );
registerAffectedTable( tableReference );
// todo (6.0) : For now we just skip the alias rendering in the delete and update clauses
// We need some dialect support if we want to support joins in delete and update statements
final Clause currentClause = clauseStack.getCurrent();
switch ( currentClause ) {
case DELETE:
case UPDATE:
return;
if ( !rendersTableReferenceAlias( currentClause ) ) {
return;
}
final String identificationVariable = tableReference.getIdentificationVariable();
if ( identificationVariable != null ) {
@ -2672,6 +2668,17 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
}
}
public static boolean rendersTableReferenceAlias(Clause clause) {
// todo (6.0) : For now we just skip the alias rendering in the delete and update clauses
// We need some dialect support if we want to support joins in delete and update statements
switch ( clause ) {
case DELETE:
case UPDATE:
return false;
}
return true;
}
protected void registerAffectedTable(TableReference tableReference) {
registerAffectedTable( tableReference.getTableExpression() );
}

View File

@ -0,0 +1,35 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.ast.spi;
/**
* A SqlAliasBase that always returns the same constant.
*
* @author Christian Beikov
*/
public class SqlAliasBaseConstant implements SqlAliasBase {
private final String constant;
public SqlAliasBaseConstant(String constant) {
this.constant = constant;
}
@Override
public String getAliasStem() {
return constant;
}
@Override
public String generateNewAlias() {
return constant;
}
@Override
public String toString() {
return "SqlAliasBase(" + constant + ")";
}
}

View File

@ -21,13 +21,13 @@ import org.hibernate.sql.results.graph.DomainResult;
*/
public class SelectStatement extends AbstractStatement {
private final QueryPart queryPart;
private final List<DomainResult> domainResults;
private final List<DomainResult<?>> domainResults;
public SelectStatement(QueryPart queryPart) {
this( queryPart, Collections.emptyList() );
}
public SelectStatement(QueryPart queryPart, List<DomainResult> domainResults) {
public SelectStatement(QueryPart queryPart, List<DomainResult<?>> domainResults) {
this( false, new LinkedHashMap<>(), queryPart, domainResults );
}
@ -35,7 +35,7 @@ public class SelectStatement extends AbstractStatement {
boolean withRecursive,
Map<String, CteStatement> cteStatements,
QueryPart queryPart,
List<DomainResult> domainResults) {
List<DomainResult<?>> domainResults) {
super( cteStatements );
this.queryPart = queryPart;
this.domainResults = domainResults;
@ -50,7 +50,7 @@ public class SelectStatement extends AbstractStatement {
return queryPart;
}
public List<DomainResult> getDomainResultDescriptors() {
public List<DomainResult<?>> getDomainResultDescriptors() {
return domainResults;
}

View File

@ -26,11 +26,11 @@ public class DomainResultGraphPrinter {
private static final boolean DEBUG_ENABLED = log.isDebugEnabled();
private static final boolean TRACE_ENABLED = log.isTraceEnabled();
public static void logDomainResultGraph(List<DomainResult> domainResults) {
public static void logDomainResultGraph(List<DomainResult<?>> domainResults) {
logDomainResultGraph( "DomainResult Graph", domainResults );
}
public static void logDomainResultGraph(String header, List<DomainResult> domainResults) {
public static void logDomainResultGraph(String header, List<DomainResult<?>> domainResults) {
if ( ! DEBUG_ENABLED ) {
return;
}
@ -46,7 +46,7 @@ public class DomainResultGraphPrinter {
buffer = new StringBuilder( header + ":" + System.lineSeparator() );
}
private void visitDomainResults(List<DomainResult> domainResults) {
private void visitDomainResults(List<DomainResult<?>> domainResults) {
for ( int i = 0; i < domainResults.size(); i++ ) {
final DomainResult<?> domainResult = domainResults.get( i );
// DomainResults should always be the base for a branch

View File

@ -43,8 +43,7 @@ public class ResultsHelper {
final Map<NavigablePath,Initializer> initializerMap = new LinkedHashMap<>();
final List<Initializer> initializers = new ArrayList<>();
//noinspection rawtypes
final List<DomainResultAssembler> assemblers = jdbcValues.getValuesMapping().resolveAssemblers(
final List<DomainResultAssembler<?>> assemblers = jdbcValues.getValuesMapping().resolveAssemblers(
new AssemblerCreationState() {
@Override
@ -83,8 +82,9 @@ public class ResultsHelper {
}
);
//noinspection rawtypes
return new StandardRowReader<>(
assemblers,
(List) assemblers,
initializers,
rowTransformer,
callback

View File

@ -29,7 +29,7 @@ public class JdbcValuesMappingProducerStandard implements JdbcValuesMappingProdu
private final JdbcValuesMapping resolvedMapping;
public JdbcValuesMappingProducerStandard(List<SqlSelection> sqlSelections, List<DomainResult> domainResults) {
public JdbcValuesMappingProducerStandard(List<SqlSelection> sqlSelections, List<DomainResult<?>> domainResults) {
resolvedMapping = new StandardJdbcValuesMapping( sqlSelections, domainResults );
}

View File

@ -49,7 +49,7 @@ public class JdbcValuesResultSetImpl extends AbstractJdbcValues {
this.executionContext = executionContext;
this.sqlSelections = valuesMapping.getSqlSelections().toArray( new SqlSelection[0] );
this.currentRowJdbcValues = new Object[ sqlSelections.length ];
this.currentRowJdbcValues = new Object[ valuesMapping.getRowSize() ];
}
private static QueryCachePutManager resolveQueryCachePutManager(

View File

@ -20,11 +20,11 @@ import org.hibernate.sql.results.jdbc.spi.JdbcValuesMapping;
*/
public class StandardJdbcValuesMapping implements JdbcValuesMapping {
private final List<SqlSelection> sqlSelections;
private final List<DomainResult> domainResults;
private final List<DomainResult<?>> domainResults;
public StandardJdbcValuesMapping(
List<SqlSelection> sqlSelections,
List<DomainResult> domainResults) {
List<DomainResult<?>> domainResults) {
this.sqlSelections = sqlSelections;
this.domainResults = domainResults;
}
@ -35,17 +35,22 @@ public class StandardJdbcValuesMapping implements JdbcValuesMapping {
}
@Override
public List<DomainResult> getDomainResults() {
public List<DomainResult<?>> getDomainResults() {
return domainResults;
}
@Override
public List<DomainResultAssembler> resolveAssemblers(AssemblerCreationState creationState) {
final List<DomainResultAssembler> assemblers = CollectionHelper.arrayList( domainResults.size() );
public int getRowSize() {
return sqlSelections.size();
}
@Override
public List<DomainResultAssembler<?>> resolveAssemblers(AssemblerCreationState creationState) {
final List<DomainResultAssembler<?>> assemblers = CollectionHelper.arrayList( domainResults.size() );
//noinspection ForLoopReplaceableByForEach
for ( int i = 0; i < domainResults.size(); i++ ) {
final DomainResultAssembler resultAssembler = domainResults.get( i ).createResultAssembler( creationState );
final DomainResultAssembler<?> resultAssembler = domainResults.get( i ).createResultAssembler( creationState );
assemblers.add( resultAssembler );
}

View File

@ -29,7 +29,9 @@ public interface JdbcValuesMapping {
*/
List<SqlSelection> getSqlSelections();
List<DomainResult> getDomainResults();
int getRowSize();
List<DomainResultAssembler> resolveAssemblers(AssemblerCreationState creationState);
List<DomainResult<?>> getDomainResults();
List<DomainResultAssembler<?>> resolveAssemblers(AssemblerCreationState creationState);
}

View File

@ -51,7 +51,7 @@ public class FunctionTests {
entity.setId(123);
entity.setTheDate( new Date( 74, 2, 25 ) );
entity.setTheTime( new Time( 23, 10, 8 ) );
entity.setTheTimestamp( new Timestamp( System.currentTimeMillis() ) );
entity.setTheTimestamp( new Timestamp( 121, 4, 27, 13, 22, 50, 123456789 ) );
em.persist(entity);
}
);

View File

@ -48,7 +48,7 @@ public class StandardFunctionTests {
entity.setId(123);
entity.setTheDate( new Date( 74, 2, 25 ) );
entity.setTheTime( new Time( 23, 10, 8 ) );
entity.setTheTimestamp( new Timestamp( System.currentTimeMillis() ) );
entity.setTheTimestamp( new Timestamp( 121, 4, 27, 13, 22, 50, 123456789 ) );
em.persist(entity);
}
);

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.annotations;
package org.hibernate.orm.test.where.annotations;
import java.util.HashSet;
import java.util.Set;

View File

@ -4,9 +4,10 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.annotations;
package org.hibernate.orm.test.where.annotations;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.persistence.CascadeType;
import javax.persistence.ElementCollection;
@ -24,6 +25,7 @@ import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;
import org.hibernate.annotations.Where;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
@ -40,6 +42,10 @@ import static org.junit.Assert.assertSame;
*/
public class EagerManyToOneFetchModeSelectWhereTest extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected void addSettings(Map settings) {
settings.put( AvailableSettings.CREATE_EMPTY_COMPOSITES_ENABLED, true );
}
@Override
protected Class[] getAnnotatedClasses() {

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.annotations;
package org.hibernate.orm.test.where.annotations;
import java.util.Arrays;
import java.util.HashSet;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.annotations;
package org.hibernate.orm.test.where.annotations;
import java.util.Arrays;
import java.util.HashSet;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.annotations;
package org.hibernate.orm.test.where.annotations;
import java.util.Arrays;
import java.util.HashSet;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.annotations;
package org.hibernate.orm.test.where.annotations;
import java.util.ArrayList;
import java.util.HashSet;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.annotations;
package org.hibernate.orm.test.where.annotations;
import java.util.ArrayList;
import java.util.HashSet;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.annotations;
package org.hibernate.orm.test.where.annotations;
import java.util.ArrayList;
import java.util.HashSet;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.annotations;
package org.hibernate.orm.test.where.annotations;
import java.util.ArrayList;
import java.util.HashSet;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.annotations;
package org.hibernate.orm.test.where.annotations;
import java.util.Arrays;
import java.util.HashSet;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.annotations;
package org.hibernate.orm.test.where.annotations;
import java.util.Arrays;
import java.util.HashSet;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.annotations;
package org.hibernate.orm.test.where.annotations;
import java.util.Arrays;
import java.util.HashSet;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.hbm;
package org.hibernate.orm.test.where.hbm;
public class Category {
private int id;

View File

@ -4,7 +4,7 @@
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.where.hbm" default-access="property">
<hibernate-mapping package="org.hibernate.orm.test.where.hbm" default-access="property">
<class name="EagerManyToOneFetchModeJoinWhereTest$Product" table="PRODUCT">
<id name="id" column="ID">
<generator class="increment" />

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.hbm;
package org.hibernate.orm.test.where.hbm;
import java.util.HashSet;
import java.util.Set;
@ -25,6 +25,12 @@ import static org.junit.Assert.assertSame;
*/
public class EagerManyToOneFetchModeJoinWhereTest extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected String getBaseForMappings() {
return "org/hibernate/orm/test/";
}
@Override
protected String[] getMappings() {
return new String[] { "where/hbm/EagerManyToOneFetchModeJoinWhereTest.hbm.xml" };
}

View File

@ -4,7 +4,7 @@
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.where.hbm" default-access="property">
<hibernate-mapping package="org.hibernate.orm.test.where.hbm" default-access="property">
<class name="EagerManyToOneFetchModeSelectWhereTest$Product" table="PRODUCT">
<id name="id" column="ID">
<generator class="increment" />

View File

@ -4,11 +4,14 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.hbm;
package org.hibernate.orm.test.where.hbm;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.Test;
@ -24,6 +27,17 @@ import static org.junit.Assert.assertSame;
*/
public class EagerManyToOneFetchModeSelectWhereTest extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected void addSettings(Map settings) {
settings.put( AvailableSettings.CREATE_EMPTY_COMPOSITES_ENABLED, true );
}
@Override
protected String getBaseForMappings() {
return "org/hibernate/orm/test/";
}
@Override
protected String[] getMappings() {
return new String[] { "where/hbm/EagerManyToOneFetchModeSelectWhereTest.hbm.xml" };
}

View File

@ -4,7 +4,7 @@
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.where.hbm" default-access="property">
<hibernate-mapping package="org.hibernate.orm.test.where.hbm" default-access="property">
<class name="Product" table="PRODUCT">
<id name="id" column="ID">
<generator class="increment" />

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.hbm;
package org.hibernate.orm.test.where.hbm;
import java.util.Arrays;
import java.util.HashSet;
@ -30,6 +30,11 @@ import static org.junit.Assert.assertTrue;
*/
public class EagerToManyWhereDontUseClassWhereTest extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected String getBaseForMappings() {
return "org/hibernate/orm/test/";
}
@Override
protected String[] getMappings() {
return new String[] { "where/hbm/EagerToManyWhere.hbm.xml" };

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.hbm;
package org.hibernate.orm.test.where.hbm;
import java.util.Arrays;
import java.util.HashSet;
@ -28,6 +28,11 @@ import static org.junit.Assert.assertTrue;
*/
public class EagerToManyWhereTest extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected String getBaseForMappings() {
return "org/hibernate/orm/test/";
}
@Override
protected String[] getMappings() {
return new String[] { "where/hbm/EagerToManyWhere.hbm.xml" };

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.hbm;
package org.hibernate.orm.test.where.hbm;
import java.util.Arrays;
import java.util.HashSet;
@ -30,6 +30,11 @@ import static org.junit.Assert.assertTrue;
*/
public class EagerToManyWhereUseClassWhereTest extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected String getBaseForMappings() {
return "org/hibernate/orm/test/";
}
@Override
protected String[] getMappings() {
return new String[] { "where/hbm/EagerToManyWhere.hbm.xml" };

View File

@ -12,7 +12,7 @@
<!--
Demonstrates use of a class-level where restriction
-->
<hibernate-mapping package="org.hibernate.test.where.hbm">
<hibernate-mapping package="org.hibernate.orm.test.where.hbm">
<class name="File" where="deleted=0" table="T_FILE">
<id name="id">

View File

@ -6,7 +6,7 @@
*/
//$Id: File.java 8043 2005-08-30 15:20:42Z oneovthafew $
package org.hibernate.test.where.hbm;
package org.hibernate.orm.test.where.hbm;
import java.util.Set;
public class File {

View File

@ -4,7 +4,7 @@
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.where.hbm" default-access="property">
<hibernate-mapping package="org.hibernate.orm.test.where.hbm" default-access="property">
<class name="LazyElementCollectionBasicNonUniqueIdWhereTest$Material" table="MAIN_TABLE" where="CODE = 'MATERIAL'">
<id name="id" column="ID">
<generator class="assigned" />

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.hbm;
package org.hibernate.orm.test.where.hbm;
import java.util.ArrayList;
import java.util.HashSet;
@ -31,6 +31,11 @@ import static org.junit.Assert.assertTrue;
@RequiresDialect(H2Dialect.class)
public class LazyElementCollectionBasicNonUniqueIdWhereTest extends BaseCoreFunctionalTestCase {
@Override
protected String getBaseForMappings() {
return "org/hibernate/orm/test/";
}
@Override
protected String[] getMappings() {
return new String[] { "where/hbm/LazyElementCollectionBasicNonUniqueIdWhereTest.hbm.xml" };

View File

@ -4,7 +4,7 @@
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.where.hbm" default-access="property">
<hibernate-mapping package="org.hibernate.orm.test.where.hbm" default-access="property">
<class name="LazyElementCollectionWithLazyManyToOneNonUniqueIdWhereTest$Material" table="MAIN_TABLE" where="CODE = 'MATERIAL'">
<id name="id" column="ID">
<generator class="assigned" />

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.hbm;
package org.hibernate.orm.test.where.hbm;
import java.util.ArrayList;
import java.util.HashSet;
@ -31,6 +31,11 @@ import static org.junit.Assert.assertTrue;
@RequiresDialect(H2Dialect.class)
public class LazyElementCollectionWithLazyManyToOneNonUniqueIdWhereTest extends BaseCoreFunctionalTestCase {
@Override
protected String getBaseForMappings() {
return "org/hibernate/orm/test/";
}
@Override
protected String[] getMappings() {
return new String[] { "where/hbm/LazyElementCollectionWithLazyManyToOneNonUniqueIdWhereTest.hbm.xml" };

View File

@ -4,7 +4,7 @@
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.where.hbm" default-access="property">
<hibernate-mapping package="org.hibernate.orm.test.where.hbm" default-access="property">
<class name="LazyManyToManyNonUniqueIdNotFoundWhereTest$Material" table="MAIN_TABLE" where="CODE = 'MATERIAL'">
<id name="id" column="ID">
<generator class="assigned" />

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.hbm;
package org.hibernate.orm.test.where.hbm;
import java.util.HashSet;
import java.util.Set;
@ -26,6 +26,12 @@ import static org.junit.Assert.assertTrue;
*/
public class LazyManyToManyNonUniqueIdNotFoundWhereTest extends BaseCoreFunctionalTestCase {
@Override
protected String getBaseForMappings() {
return "org/hibernate/orm/test/";
}
@Override
protected String[] getMappings() {
return new String[] { "where/hbm/LazyManyToManyNonUniqueIdNotFoundWhereTest.hbm.xml" };
}

View File

@ -4,7 +4,7 @@
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.where.hbm" default-access="property">
<hibernate-mapping package="org.hibernate.orm.test.where.hbm" default-access="property">
<class name="LazyManyToManyNonUniqueIdWhereTest$Material" table="MAIN_TABLE" where="CODE = 'MATERIAL'">
<id name="id" column="ID">
<generator class="assigned" />

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.hbm;
package org.hibernate.orm.test.where.hbm;
import java.util.ArrayList;
import java.util.HashSet;
@ -33,6 +33,12 @@ import static org.junit.Assert.fail;
*/
public class LazyManyToManyNonUniqueIdWhereTest extends BaseCoreFunctionalTestCase {
@Override
protected String getBaseForMappings() {
return "org/hibernate/orm/test/";
}
@Override
protected String[] getMappings() {
return new String[] { "where/hbm/LazyManyToManyNonUniqueIdWhereTest.hbm.xml" };
}

View File

@ -4,7 +4,7 @@
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.where.hbm" default-access="property">
<hibernate-mapping package="org.hibernate.orm.test.where.hbm" default-access="property">
<class name="LazyOneToManyNonUniqueIdWhereTest$Material" table="MAIN_TABLE" where="CODE = 'MATERIAL'">
<id name="id" column="ID">
<generator class="assigned" />

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.hbm;
package org.hibernate.orm.test.where.hbm;
import java.util.ArrayList;
import java.util.HashSet;
@ -33,6 +33,12 @@ import static org.junit.Assert.fail;
*/
public class LazyOneToManyNonUniqueIdWhereTest extends BaseCoreFunctionalTestCase {
@Override
protected String getBaseForMappings() {
return "org/hibernate/orm/test/";
}
@Override
protected String[] getMappings() {
return new String[] { "where/hbm/LazyOneToManyNonUniqueIdWhereTest.hbm.xml" };
}

View File

@ -4,7 +4,7 @@
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="org.hibernate.test.where.hbm" default-access="property">
<hibernate-mapping package="org.hibernate.orm.test.where.hbm" default-access="property">
<class name="Product" table="PRODUCT">
<id name="id" column="ID">
<generator class="increment" />

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.hbm;
package org.hibernate.orm.test.where.hbm;
import java.util.Arrays;
import java.util.HashSet;
@ -30,6 +30,11 @@ import static org.junit.Assert.assertTrue;
*/
public class LazyToManyWhereDontUseClassWhereTest extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected String getBaseForMappings() {
return "org/hibernate/orm/test/";
}
@Override
protected String[] getMappings() {
return new String[] { "where/hbm/LazyToManyWhere.hbm.xml" };

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.hbm;
package org.hibernate.orm.test.where.hbm;
import java.util.Arrays;
import java.util.HashSet;
@ -28,6 +28,11 @@ import static org.junit.Assert.assertTrue;
*/
public class LazyToManyWhereTest extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected String getBaseForMappings() {
return "org/hibernate/orm/test/";
}
@Override
protected String[] getMappings() {
return new String[] { "where/hbm/LazyToManyWhere.hbm.xml" };

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.hbm;
package org.hibernate.orm.test.where.hbm;
import java.util.Arrays;
import java.util.HashSet;
@ -30,6 +30,11 @@ import static org.junit.Assert.assertTrue;
*/
public class LazyToManyWhereUseClassWhereTest extends BaseNonConfigCoreFunctionalTestCase {
@Override
protected String getBaseForMappings() {
return "org/hibernate/orm/test/";
}
@Override
protected String[] getMappings() {
return new String[] { "where/hbm/LazyToManyWhere.hbm.xml" };

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.hbm;
package org.hibernate.orm.test.where.hbm;
import java.util.HashSet;
import java.util.Set;

View File

@ -4,14 +4,13 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.test.where.hbm;
package org.hibernate.orm.test.where.hbm;
import java.util.HashSet;
import java.util.List;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Root;
@ -30,6 +29,13 @@ import static org.junit.Assert.assertNull;
* @author Max Rydahl Andersen
*/
public class WhereTest extends BaseCoreFunctionalTestCase {
@Override
protected String getBaseForMappings() {
return "org/hibernate/orm/test/";
}
@Override
public String[] getMappings() {
return new String[] { "where/hbm/File.hbm.xml" };
}
@ -59,8 +65,8 @@ public class WhereTest extends BaseCoreFunctionalTestCase {
public void removeTestData() {
inTransaction(
s -> {
s.createQuery( "update File f set f.parent = null" ).executeUpdate();
s.createQuery( "delete File f" ).executeUpdate();
s.createNativeQuery( "update T_FILE set parent = null" ).executeUpdate();
s.createNativeQuery( "delete from T_FILE" ).executeUpdate();
}
);
}
@ -104,11 +110,6 @@ public class WhereTest extends BaseCoreFunctionalTestCase {
criteria.where( criteriaBuilder.isNull( root.get("parent") ));
File parent = s.createQuery( criteria ).uniqueResult();
assertEquals( parent.getChildren().size(), 1 );
// File parent = (File) s.createCriteria( File.class )
// .setFetchMode( "children", FetchMode.JOIN )
// .add( Restrictions.isNull( "parent" ) )
// .uniqueResult();
assertEquals( 1, parent.getChildren().size() );
}
);
@ -123,7 +124,7 @@ public class WhereTest extends BaseCoreFunctionalTestCase {
.addEntity( "f", File.class );
query.addFetch( "c", "f", "children" );
File parent = (File) ( (Object[]) query.list().get( 0 ) )[0];
File parent = (File) query.list().get( 0 );
// @Where should not be applied
assertEquals( 2, parent.getChildren().size() );
}