Implement envers order fragment support by introducing an internal sqm function and re-enable all envers tests

This commit is contained in:
Christian Beikov 2021-09-01 18:15:14 +02:00
parent 04ac8b13c3
commit 65016aaf42
16 changed files with 332 additions and 74 deletions

View File

@ -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 );

View File

@ -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 );
}

View File

@ -23,6 +23,10 @@ dependencies {
testImplementation project( ':hibernate-testing' )
}
test {
include '**/**'
}
sourceSets {
test {
ext {

View File

@ -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 );
}
}

View File

@ -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.

View File

@ -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 {

View File

@ -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();
}
}
}

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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 ) {

View File

@ -0,0 +1 @@
org.hibernate.envers.boot.internal.FunctionContributorImpl

View File

@ -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"/>

View File

@ -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 }