Implement envers order fragment support by introducing an internal sqm function and re-enable all envers tests
This commit is contained in:
parent
04ac8b13c3
commit
65016aaf42
|
@ -1464,7 +1464,10 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
try {
|
||||
for ( SqmSortSpecification sortSpecification : sqmQueryPart.getOrderByClause()
|
||||
.getSortSpecifications() ) {
|
||||
sqlQueryPart.addSortSpecification( visitSortSpecification( sortSpecification ) );
|
||||
final SortSpecification specification = visitSortSpecification( sortSpecification );
|
||||
if ( specification != null ) {
|
||||
sqlQueryPart.addSortSpecification( specification );
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
|
@ -1777,8 +1780,12 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
|
||||
@Override
|
||||
public SortSpecification visitSortSpecification(SqmSortSpecification sortSpecification) {
|
||||
final Expression expression = resolveGroupOrOrderByExpression( sortSpecification.getSortExpression() );
|
||||
if ( expression == null ) {
|
||||
return null;
|
||||
}
|
||||
return new SortSpecification(
|
||||
resolveGroupOrOrderByExpression( sortSpecification.getSortExpression() ),
|
||||
expression,
|
||||
null,
|
||||
sortSpecification.getSortOrder(),
|
||||
sortSpecification.getNullPrecedence()
|
||||
|
@ -1850,6 +1857,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
if ( fromClauseIndex.isResolved( sqmRoot ) ) {
|
||||
log.tracef( "Already resolved SqmRoot [%s] to TableGroup", sqmRoot );
|
||||
}
|
||||
final QuerySpec currentQuerySpec = currentQuerySpec();
|
||||
final TableGroup tableGroup;
|
||||
if ( sqmRoot.isCorrelated() ) {
|
||||
final SessionFactoryImplementor sessionFactory = creationContext.getSessionFactory();
|
||||
|
@ -1863,7 +1871,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
tableGroup = new CorrelatedTableGroup(
|
||||
parentTableGroup,
|
||||
sqlAliasBase,
|
||||
currentQuerySpec(),
|
||||
currentQuerySpec,
|
||||
predicate -> additionalRestrictions = SqlAstTreeHelper.combinePredicates(
|
||||
additionalRestrictions,
|
||||
predicate
|
||||
|
@ -1955,12 +1963,20 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
this,
|
||||
creationContext
|
||||
);
|
||||
final FilterPredicate filterPredicate = FilterHelper.createFilterPredicate(
|
||||
getLoadQueryInfluencers(),
|
||||
(Joinable) entityDescriptor,
|
||||
tableGroup
|
||||
);
|
||||
if ( filterPredicate != null ) {
|
||||
currentQuerySpec.applyPredicate( filterPredicate );
|
||||
}
|
||||
}
|
||||
|
||||
log.tracef( "Resolved SqmRoot [%s] to new TableGroup [%s]", sqmRoot, tableGroup );
|
||||
|
||||
fromClauseIndex.register( sqmRoot, tableGroup );
|
||||
currentQuerySpec().getFromClause().addRoot( tableGroup );
|
||||
currentQuerySpec.getFromClause().addRoot( tableGroup );
|
||||
|
||||
consumeReusablePaths( sqmRoot, tableGroup );
|
||||
consumeExplicitJoins( sqmRoot, tableGroup );
|
||||
|
|
|
@ -38,6 +38,10 @@ public class FromClauseIndex extends SimpleFromClauseAccessImpl {
|
|||
super( parent );
|
||||
}
|
||||
|
||||
public TableGroup findTableGroup(String alias) {
|
||||
return tableGroupByAliasXref.get( alias );
|
||||
}
|
||||
|
||||
public void register(SqmPath<?> sqmPath, TableGroup tableGroup) {
|
||||
register( sqmPath, tableGroup, null );
|
||||
}
|
||||
|
|
|
@ -23,6 +23,10 @@ dependencies {
|
|||
testImplementation project( ':hibernate-testing' )
|
||||
}
|
||||
|
||||
test {
|
||||
include '**/**'
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
test {
|
||||
ext {
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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.envers.boot.internal;
|
||||
|
||||
import org.hibernate.boot.model.FunctionContributor;
|
||||
import org.hibernate.boot.model.TypeContributions;
|
||||
import org.hibernate.boot.model.TypeContributor;
|
||||
import org.hibernate.envers.function.OrderByFragmentFunction;
|
||||
import org.hibernate.envers.internal.entities.RevisionTypeType;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||
import org.hibernate.service.ServiceRegistry;
|
||||
|
||||
/**
|
||||
* Envers specific FunctionContributor
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class FunctionContributorImpl implements FunctionContributor {
|
||||
|
||||
@Override
|
||||
public void contributeFunctions(SqmFunctionRegistry functionRegistry, ServiceRegistry serviceRegistry) {
|
||||
final EnversService enversService = serviceRegistry.getService( EnversService.class );
|
||||
if ( !enversService.isEnabled() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
functionRegistry.register( OrderByFragmentFunction.FUNCTION_NAME, OrderByFragmentFunction.INSTANCE );
|
||||
}
|
||||
|
||||
}
|
|
@ -243,7 +243,9 @@ public final class CollectionMetadataGenerator {
|
|||
isEmbeddableElementType(),
|
||||
mappedBy,
|
||||
isMappedByKey( propertyValue, mappedBy ),
|
||||
propertyValue.getOrderBy()
|
||||
propertyValue.getOrderBy() == null
|
||||
? null
|
||||
: propertyValue.getRole()
|
||||
);
|
||||
|
||||
// Creating common mapper data.
|
||||
|
@ -461,6 +463,9 @@ public final class CollectionMetadataGenerator {
|
|||
// Creating a query generator builder, to which additional id data will be added, in case this collection
|
||||
// references some entities (either from the element or index). At the end, this will be used to build
|
||||
// a query generator to read the raw data collection from the middle table.
|
||||
final String orderBy = propertyValue.getOrderBy() == null
|
||||
? propertyValue.getManyToManyOrdering()
|
||||
: propertyValue.getOrderBy();
|
||||
final QueryGeneratorBuilder queryGeneratorBuilder = new QueryGeneratorBuilder(
|
||||
mainGenerator.getGlobalCfg(),
|
||||
mainGenerator.getVerEntCfg(),
|
||||
|
@ -468,9 +473,9 @@ public final class CollectionMetadataGenerator {
|
|||
referencingIdData,
|
||||
auditMiddleEntityName,
|
||||
isRevisionTypeInId(),
|
||||
propertyValue.getOrderBy() == null
|
||||
? propertyValue.getManyToManyOrdering()
|
||||
: propertyValue.getOrderBy()
|
||||
orderBy == null
|
||||
? null
|
||||
: propertyValue.getRole()
|
||||
);
|
||||
|
||||
// Adding the XML mapping for the referencing entity, if the relation isn't inverse.
|
||||
|
|
|
@ -36,7 +36,7 @@ public final class QueryGeneratorBuilder {
|
|||
private final String auditMiddleEntityName;
|
||||
private final List<MiddleIdData> idDatas;
|
||||
private final boolean revisionTypeInId;
|
||||
private final String orderBy;
|
||||
private final String orderByCollectionRole;
|
||||
|
||||
QueryGeneratorBuilder(
|
||||
GlobalConfiguration globalCfg,
|
||||
|
@ -45,13 +45,13 @@ public final class QueryGeneratorBuilder {
|
|||
MiddleIdData referencingIdData,
|
||||
String auditMiddleEntityName,
|
||||
boolean revisionTypeInId,
|
||||
String orderBy) {
|
||||
String orderByCollectionRole) {
|
||||
this.globalCfg = globalCfg;
|
||||
this.verEntCfg = verEntCfg;
|
||||
this.auditStrategy = auditStrategy;
|
||||
this.referencingIdData = referencingIdData;
|
||||
this.auditMiddleEntityName = auditMiddleEntityName;
|
||||
this.orderBy = orderBy;
|
||||
this.orderByCollectionRole = orderByCollectionRole;
|
||||
this.revisionTypeInId = revisionTypeInId;
|
||||
|
||||
idDatas = new ArrayList<>();
|
||||
|
@ -72,13 +72,13 @@ public final class QueryGeneratorBuilder {
|
|||
if ( idDatas.get( 0 ).isAudited() ) {
|
||||
return new TwoEntityQueryGenerator(
|
||||
globalCfg, verEntCfg, auditStrategy, auditMiddleEntityName, referencingIdData,
|
||||
idDatas.get( 0 ), revisionTypeInId, orderBy, componentDatas
|
||||
idDatas.get( 0 ), revisionTypeInId, orderByCollectionRole, componentDatas
|
||||
);
|
||||
}
|
||||
else {
|
||||
return new TwoEntityOneAuditedQueryGenerator(
|
||||
globalCfg, verEntCfg, auditStrategy, auditMiddleEntityName, referencingIdData,
|
||||
idDatas.get( 0 ), revisionTypeInId, orderBy, componentDatas
|
||||
idDatas.get( 0 ), revisionTypeInId, orderByCollectionRole, componentDatas
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ public final class QueryGeneratorBuilder {
|
|||
}
|
||||
return new ThreeEntityQueryGenerator(
|
||||
globalCfg, verEntCfg, auditStrategy, auditMiddleEntityName, referencingIdData,
|
||||
idDatas.get( 0 ), idDatas.get( 1 ), revisionTypeInId, orderBy, componentDatas
|
||||
idDatas.get( 0 ), idDatas.get( 1 ), revisionTypeInId, orderByCollectionRole, componentDatas
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
/*
|
||||
* 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.envers.function;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.ModelPartContainer;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
import org.hibernate.metamodel.mapping.ordering.OrderByFragment;
|
||||
import org.hibernate.metamodel.model.domain.AllowableFunctionReturnType;
|
||||
import org.hibernate.persister.collection.QueryableCollection;
|
||||
import org.hibernate.persister.entity.Joinable;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
|
||||
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
|
||||
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
|
||||
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
|
||||
import org.hibernate.query.sqm.sql.FromClauseIndex;
|
||||
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.query.sqm.tree.expression.SqmLiteral;
|
||||
import org.hibernate.sql.ast.spi.SqlAstQueryPartProcessingState;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
|
||||
import org.hibernate.sql.ast.tree.select.QuerySpec;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
* Envers specific FunctionContributor
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class OrderByFragmentFunction extends AbstractSqmFunctionDescriptor {
|
||||
|
||||
public static final String FUNCTION_NAME = "_order_by_frag";
|
||||
public static final OrderByFragmentFunction INSTANCE = new OrderByFragmentFunction();
|
||||
|
||||
public OrderByFragmentFunction() {
|
||||
super(
|
||||
FUNCTION_NAME,
|
||||
StandardArgumentsValidators.exactly( 2 ),
|
||||
StandardFunctionReturnTypeResolvers.useArgType( 1 )
|
||||
);
|
||||
}
|
||||
@Override
|
||||
protected <T> SelfRenderingSqmFunction<T> generateSqmFunctionExpression(
|
||||
List<? extends SqmTypedNode<?>> arguments,
|
||||
AllowableFunctionReturnType<T> impliedResultType,
|
||||
QueryEngine queryEngine,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return new SelfRenderingSqmFunction<T>(
|
||||
this,
|
||||
null,
|
||||
arguments,
|
||||
impliedResultType,
|
||||
getReturnTypeResolver(),
|
||||
queryEngine.getCriteriaBuilder(),
|
||||
getName()
|
||||
) {
|
||||
|
||||
@Override
|
||||
public SelfRenderingFunctionSqlAstExpression convertToSqlAst(SqmToSqlAstConverter walker) {
|
||||
final AllowableFunctionReturnType<?> resultType = resolveResultType(
|
||||
walker.getCreationContext().getDomainModel().getTypeConfiguration()
|
||||
);
|
||||
final String sqmAlias = ( (SqmLiteral<String>) getArguments().get( 0 ) ).getLiteralValue();
|
||||
final String attributeRole = ( (SqmLiteral<String>) getArguments().get( 1 ) ).getLiteralValue();
|
||||
final TableGroup tableGroup = ( (FromClauseIndex) walker.getFromClauseAccess() ).findTableGroup(
|
||||
sqmAlias
|
||||
);
|
||||
final QueryableCollection collectionDescriptor = (QueryableCollection) walker.getCreationContext()
|
||||
.getDomainModel()
|
||||
.findCollectionDescriptor( attributeRole );
|
||||
final PluralAttributeMapping pluralAttribute = collectionDescriptor.getAttributeMapping();
|
||||
final QuerySpec queryPart = (QuerySpec) ( (SqlAstQueryPartProcessingState) walker.getCurrentProcessingState() ).getInflightQueryPart();
|
||||
final OrderByFragment fragment;
|
||||
if ( pluralAttribute.getOrderByFragment() != null ) {
|
||||
fragment = pluralAttribute.getOrderByFragment();
|
||||
}
|
||||
else {
|
||||
fragment = pluralAttribute.getManyToManyOrderByFragment();
|
||||
}
|
||||
final String targetTableExpression;
|
||||
if ( collectionDescriptor.getElementPersister() == null ) {
|
||||
targetTableExpression = collectionDescriptor.getTableName();
|
||||
}
|
||||
else {
|
||||
targetTableExpression = ( (Joinable) collectionDescriptor.getElementPersister() ).getTableName();
|
||||
}
|
||||
// We apply the fragment here and return null to signal that this is a no-op
|
||||
fragment.apply(
|
||||
queryPart,
|
||||
new AuditingTableGroup( tableGroup, targetTableExpression ),
|
||||
walker
|
||||
);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static class AuditingTableGroup implements TableGroup {
|
||||
|
||||
private final TableGroup delegate;
|
||||
private final String auditTableExpression;
|
||||
private final String normalTableExpression;
|
||||
|
||||
public AuditingTableGroup(TableGroup delegate, String normalTableExpression) {
|
||||
this.delegate = delegate;
|
||||
this.auditTableExpression = delegate.getPrimaryTableReference().getTableExpression();
|
||||
this.normalTableExpression = normalTableExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelPart getExpressionType() {
|
||||
return delegate.getExpressionType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(
|
||||
NavigablePath navigablePath,
|
||||
String tableExpression,
|
||||
boolean allowFkOptimization) {
|
||||
if ( tableExpression.equals( normalTableExpression ) ) {
|
||||
tableExpression = auditTableExpression;
|
||||
}
|
||||
return delegate.resolveTableReference( navigablePath, tableExpression, allowFkOptimization );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference getTableReference(
|
||||
NavigablePath navigablePath,
|
||||
String tableExpression,
|
||||
boolean allowFkOptimization) {
|
||||
if ( tableExpression.equals( normalTableExpression ) ) {
|
||||
tableExpression = auditTableExpression;
|
||||
}
|
||||
return delegate.getTableReference( navigablePath, tableExpression, allowFkOptimization );
|
||||
}
|
||||
|
||||
@Override
|
||||
public NavigablePath getNavigablePath() {
|
||||
return delegate.getNavigablePath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGroupAlias() {
|
||||
return delegate.getGroupAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelPartContainer getModelPart() {
|
||||
return delegate.getModelPart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSourceAlias() {
|
||||
return delegate.getSourceAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TableGroupJoin> getTableGroupJoins() {
|
||||
return delegate.getTableGroupJoins();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUseInnerJoins() {
|
||||
return delegate.canUseInnerJoins();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasTableGroupJoins() {
|
||||
return delegate.hasTableGroupJoins();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTableGroupJoin(TableGroupJoin join) {
|
||||
delegate.addTableGroupJoin( join );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||
delegate.visitTableGroupJoins( consumer );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyAffectedTableNames(Consumer<String> nameCollector) {
|
||||
delegate.applyAffectedTableNames( nameCollector );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference getPrimaryTableReference() {
|
||||
return delegate.getPrimaryTableReference();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TableReferenceJoin> getTableReferenceJoins() {
|
||||
return delegate.getTableReferenceJoins();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -40,7 +40,7 @@ public abstract class AbstractRelationQueryGenerator implements RelationQueryGen
|
|||
protected final MiddleIdData referencingIdData;
|
||||
protected final boolean revisionTypeInId;
|
||||
protected final String entityName;
|
||||
protected final String orderBy;
|
||||
protected final String orderByCollectionRole;
|
||||
|
||||
private String queryString;
|
||||
private String queryRemovedString;
|
||||
|
@ -52,14 +52,14 @@ public abstract class AbstractRelationQueryGenerator implements RelationQueryGen
|
|||
String entityName,
|
||||
MiddleIdData referencingIdData,
|
||||
boolean revisionTypeInId,
|
||||
String orderBy) {
|
||||
String orderByCollectionRole) {
|
||||
this.globalCfg = globalCfg;
|
||||
this.verEntCfg = verEntCfg;
|
||||
this.entityName = entityName;
|
||||
this.auditStrategy = auditStrategy;
|
||||
this.referencingIdData = referencingIdData;
|
||||
this.revisionTypeInId = revisionTypeInId;
|
||||
this.orderBy = orderBy;
|
||||
this.orderByCollectionRole = orderByCollectionRole;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -44,7 +44,7 @@ public final class OneAuditEntityQueryGenerator extends AbstractRelationQueryGen
|
|||
boolean revisionTypeInId,
|
||||
String mappedBy,
|
||||
boolean mappedByKey,
|
||||
String orderBy) {
|
||||
String orderByCollectionRole) {
|
||||
super(
|
||||
globalCfg,
|
||||
verEntCfg,
|
||||
|
@ -52,7 +52,7 @@ public final class OneAuditEntityQueryGenerator extends AbstractRelationQueryGen
|
|||
verEntCfg.getAuditEntityName( referencedEntityName ),
|
||||
referencingIdData,
|
||||
revisionTypeInId,
|
||||
orderBy
|
||||
orderByCollectionRole
|
||||
);
|
||||
|
||||
this.mappedBy = mappedBy;
|
||||
|
@ -106,8 +106,8 @@ public final class OneAuditEntityQueryGenerator extends AbstractRelationQueryGen
|
|||
}
|
||||
|
||||
// ORDER BY
|
||||
if ( !StringHelper.isEmpty( orderBy ) ) {
|
||||
qb.addOrderFragment( REFERENCED_ENTITY_ALIAS, orderBy );
|
||||
if ( !StringHelper.isEmpty( orderByCollectionRole ) ) {
|
||||
qb.addOrderFragment( REFERENCED_ENTITY_ALIAS, orderByCollectionRole );
|
||||
}
|
||||
|
||||
return qb;
|
||||
|
|
|
@ -45,7 +45,7 @@ public final class ThreeEntityQueryGenerator extends AbstractRelationQueryGenera
|
|||
MiddleIdData referencedIdData,
|
||||
MiddleIdData indexIdData,
|
||||
boolean revisionTypeInId,
|
||||
String orderBy,
|
||||
String orderByCollectionRole,
|
||||
MiddleComponentData... componentData) {
|
||||
super(
|
||||
globalCfg,
|
||||
|
@ -54,7 +54,7 @@ public final class ThreeEntityQueryGenerator extends AbstractRelationQueryGenera
|
|||
versionsMiddleEntityName,
|
||||
referencingIdData,
|
||||
revisionTypeInId,
|
||||
orderBy
|
||||
orderByCollectionRole
|
||||
);
|
||||
|
||||
this.referencedIdData = referencedIdData;
|
||||
|
@ -139,8 +139,8 @@ public final class ThreeEntityQueryGenerator extends AbstractRelationQueryGenera
|
|||
// ORDER BY
|
||||
// Hibernate applies @OrderBy on map elements, not the key.
|
||||
// So here we apply it to the referenced entity, not the actual index entity that represents the key.
|
||||
if ( !StringHelper.isEmpty( orderBy ) ) {
|
||||
qb.addOrderFragment( REFERENCED_ENTITY_ALIAS, orderBy );
|
||||
if ( !StringHelper.isEmpty( orderByCollectionRole ) ) {
|
||||
qb.addOrderFragment( REFERENCED_ENTITY_ALIAS, orderByCollectionRole );
|
||||
}
|
||||
return qb;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ public final class TwoEntityOneAuditedQueryGenerator extends AbstractRelationQue
|
|||
MiddleIdData referencingIdData,
|
||||
MiddleIdData referencedIdData,
|
||||
boolean revisionTypeInId,
|
||||
String orderBy,
|
||||
String orderorderByCollectionRoley,
|
||||
MiddleComponentData... componentData) {
|
||||
super(
|
||||
globalCfg,
|
||||
|
@ -49,7 +49,7 @@ public final class TwoEntityOneAuditedQueryGenerator extends AbstractRelationQue
|
|||
versionsMiddleEntityName,
|
||||
referencingIdData,
|
||||
revisionTypeInId,
|
||||
orderBy
|
||||
orderorderByCollectionRoley
|
||||
);
|
||||
|
||||
this.referencedIdData = referencedIdData;
|
||||
|
@ -96,8 +96,8 @@ public final class TwoEntityOneAuditedQueryGenerator extends AbstractRelationQue
|
|||
// ee.originalId.id_ref_ing = :id_ref_ing
|
||||
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery( rootParameters, originalIdPropertyName, true );
|
||||
// ORDER BY
|
||||
if ( !StringHelper.isEmpty( orderBy ) ) {
|
||||
qb.addOrderFragment( REFERENCED_ENTITY_ALIAS, orderBy );
|
||||
if ( !StringHelper.isEmpty( orderByCollectionRole ) ) {
|
||||
qb.addOrderFragment( REFERENCED_ENTITY_ALIAS, orderByCollectionRole );
|
||||
}
|
||||
return qb;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.envers.internal.entities.mapper.relation.query;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.envers.configuration.internal.AuditEntitiesConfiguration;
|
||||
import org.hibernate.envers.configuration.internal.GlobalConfiguration;
|
||||
import org.hibernate.envers.internal.entities.mapper.relation.MiddleComponentData;
|
||||
|
@ -42,7 +41,7 @@ public final class TwoEntityQueryGenerator extends AbstractRelationQueryGenerato
|
|||
MiddleIdData referencingIdData,
|
||||
MiddleIdData referencedIdData,
|
||||
boolean revisionTypeInId,
|
||||
String orderBy,
|
||||
String orderByCollectionRole,
|
||||
MiddleComponentData... componentData) {
|
||||
super(
|
||||
globalCfg,
|
||||
|
@ -51,7 +50,7 @@ public final class TwoEntityQueryGenerator extends AbstractRelationQueryGenerato
|
|||
versionsMiddleEntityName,
|
||||
referencingIdData,
|
||||
revisionTypeInId,
|
||||
orderBy
|
||||
orderByCollectionRole
|
||||
);
|
||||
|
||||
this.referencedIdData = referencedIdData;
|
||||
|
@ -109,8 +108,8 @@ public final class TwoEntityQueryGenerator extends AbstractRelationQueryGenerato
|
|||
referencingIdData.getPrefixedMapper().addNamedIdEqualsToQuery( rootParameters, originalIdPropertyName, true );
|
||||
|
||||
// ORDER BY
|
||||
if ( !StringHelper.isEmpty( orderBy ) ) {
|
||||
qb.addOrderFragment( REFERENCED_ENTITY_ALIAS, orderBy );
|
||||
if ( !StringHelper.isEmpty( orderByCollectionRole ) ) {
|
||||
qb.addOrderFragment( REFERENCED_ENTITY_ALIAS, orderByCollectionRole );
|
||||
}
|
||||
|
||||
return qb;
|
||||
|
|
|
@ -8,21 +8,23 @@ package org.hibernate.envers.internal.tools.query;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import javax.persistence.criteria.JoinType;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.envers.RevisionType;
|
||||
import org.hibernate.envers.function.OrderByFragmentFunction;
|
||||
import org.hibernate.envers.internal.entities.RevisionTypeType;
|
||||
import org.hibernate.envers.internal.tools.MutableInteger;
|
||||
import org.hibernate.envers.internal.tools.StringTools;
|
||||
import org.hibernate.envers.internal.tools.Triple;
|
||||
import org.hibernate.envers.tools.Pair;
|
||||
import org.hibernate.query.Query;
|
||||
import org.hibernate.query.internal.QueryLiteralHelper;
|
||||
import org.hibernate.type.BasicType;
|
||||
|
||||
/**
|
||||
|
@ -186,8 +188,8 @@ public class QueryBuilder {
|
|||
orders.add( Triple.make( alias, propertyName, ascending ) );
|
||||
}
|
||||
|
||||
public void addOrderFragment(String alias, String fragment) {
|
||||
orderFragments.add( Pair.make( alias, fragment ) );
|
||||
public void addOrderFragment(String alias, String orderByCollectionRole) {
|
||||
orderFragments.add( Pair.make( alias, orderByCollectionRole ) );
|
||||
}
|
||||
|
||||
public void addProjection(String function, String alias, String propertyName, boolean distinct) {
|
||||
|
@ -247,47 +249,25 @@ public class QueryBuilder {
|
|||
StringTools.append( sb, getOrderList().iterator(), ", " );
|
||||
}
|
||||
else if ( !orderFragments.isEmpty() ) {
|
||||
// todo (6.0) : How to backport HHH-12992 to use Template#translateOrderBy from main?
|
||||
throw new NotYetImplementedFor6Exception( getClass() );
|
||||
sb.append( " order by " );
|
||||
|
||||
// sb.append( " order by " );
|
||||
//
|
||||
// final Iterator<Pair<String, String>> fragmentIterator = orderFragments.iterator();
|
||||
// while( fragmentIterator.hasNext() ) {
|
||||
// final Pair<String, String> fragment = fragmentIterator.next();
|
||||
// final OrderByTranslation orderByFragmentTranslation = Template.translateOrderBy(
|
||||
// fragment.getSecond(),
|
||||
// new ColumnMapper() {
|
||||
// @Override
|
||||
// public SqlValueReference[] map(String reference) throws HibernateException {
|
||||
// return new SqlValueReference[ 0 ];
|
||||
// }
|
||||
// },
|
||||
// sessionFactory,
|
||||
// sessionFactory.getJdbcServices().getDialect(),
|
||||
// sessionFactory.getSqlFunctionRegistry()
|
||||
// );
|
||||
//
|
||||
// sb.append( orderByFragmentTranslation.injectAliases( new QueryOrderByAliasResolver( fragment.getFirst() ) ) );
|
||||
// if ( fragmentIterator.hasNext() ) {
|
||||
// sb.append( ", " );
|
||||
// }
|
||||
// }
|
||||
final Iterator<Pair<String, String>> fragmentIterator = orderFragments.iterator();
|
||||
while( fragmentIterator.hasNext() ) {
|
||||
final Pair<String, String> fragment = fragmentIterator.next();
|
||||
sb.append( OrderByFragmentFunction.FUNCTION_NAME ).append( '(' );
|
||||
// The first argument is the sqm alias of the from node
|
||||
QueryLiteralHelper.appendStringLiteral( sb, fragment.getFirst() );
|
||||
sb.append( ", " );
|
||||
// The second argument is the collection role that contains the order by fragment
|
||||
QueryLiteralHelper.appendStringLiteral( sb, fragment.getSecond() );
|
||||
sb.append( ')' );
|
||||
if ( fragmentIterator.hasNext() ) {
|
||||
sb.append( ", " );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// private class QueryOrderByAliasResolver implements OrderByAliasResolver {
|
||||
// private String alias;
|
||||
// public QueryOrderByAliasResolver(String alias) {
|
||||
// this.alias = alias;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String resolveTableAlias(String columnReference) {
|
||||
// return alias;
|
||||
// }
|
||||
// }
|
||||
|
||||
private List<String> getSelectAliasList() {
|
||||
final List<String> aliasList = new ArrayList<>();
|
||||
for ( JoinParameter from : froms ) {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
org.hibernate.envers.boot.internal.FunctionContributorImpl
|
|
@ -16,6 +16,9 @@
|
|||
<bean id="typeContributor" class="org.hibernate.envers.boot.internal.TypeContributorImpl"/>
|
||||
<service ref="typeContributor" interface="org.hibernate.boot.model.TypeContributor"/>
|
||||
|
||||
<bean id="functionContributor" class="org.hibernate.envers.boot.internal.FunctionContributorImpl"/>
|
||||
<service ref="functionContributor" interface="org.hibernate.boot.model.FunctionContributor"/>
|
||||
|
||||
<bean id="serviceContributor" class="org.hibernate.envers.boot.internal.EnversServiceContributor"/>
|
||||
<service ref="serviceContributor" interface="org.hibernate.service.spi.ServiceContributor"/>
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ processResources {
|
|||
dependencies {
|
||||
implementation( project(':hibernate-core') ) { transitive = false }
|
||||
implementation( libraries.jpa ) { transitive = false }
|
||||
implementation( libraries.jta ) { transitive = false }
|
||||
implementation( libraries.maven_core ) { transitive = false }
|
||||
implementation( libraries.maven_artifact ) { transitive = false }
|
||||
implementation( libraries.maven_plugin ) { transitive = false }
|
||||
|
|
Loading…
Reference in New Issue