下面列出了怎么用org.hibernate.hql.internal.ast.tree.QueryNode的API类实例代码及写法,或者点击链接到github查看源代码。
private void addJoinNodes(QueryNode query, JoinSequence join, FromElement fromElement) {
JoinFragment joinFragment = join.toJoinFragment(
walker.getEnabledFilters(),
fromElement.useFromFragment() || fromElement.isDereferencedBySuperclassOrSubclassProperty(),
fromElement.getWithClauseFragment()
);
String frag = joinFragment.toFromFragmentString();
String whereFrag = joinFragment.toWhereFragmentString();
// If the from element represents a JOIN_FRAGMENT and it is
// a theta-style join, convert its type from JOIN_FRAGMENT
// to FROM_FRAGMENT
if ( fromElement.getType() == JOIN_FRAGMENT &&
( join.isThetaStyle() || StringHelper.isNotEmpty( whereFrag ) ) ) {
fromElement.setType( FROM_FRAGMENT );
fromElement.getJoinSequence().setUseThetaStyle( true ); // this is used during SqlGenerator processing
}
// If there is a FROM fragment and the FROM element is an explicit, then add the from part.
if ( fromElement.useFromFragment() ||
( fromElement.getFromClause().isSubQuery()
&& fromElement.isDereferencedBySuperclassOrSubclassProperty() ) /*&& StringHelper.isNotEmpty( frag )*/ ) {
String fromFragment = processFromFragment( frag, join ).trim();
LOG.debugf( "Using FROM fragment [%s]", fromFragment );
processDynamicFilterParameters(
fromFragment,
fromElement,
walker
);
}
syntheticAndFactory.addWhereFragment(
joinFragment,
whereFrag,
query,
fromElement,
walker
);
}
private void createSelectClauseFromFromClause(QueryNode qn) throws SemanticException {
AST select = astFactory.create( SELECT_CLAUSE, "{derived select clause}" );
AST sibling = qn.getFromClause();
qn.setFirstChild( select );
select.setNextSibling( sibling );
selectClause = (SelectClause) select;
selectClause.initializeDerivedSelectClause( currentFromClause );
LOG.debug( "Derived SELECT clause created." );
}
public CompletionStage<List<Object>> reactiveList(SharedSessionContractImplementor session, QueryParameters queryParameters) throws HibernateException {
// Delegate to the QueryLoader...
errorIfDML();
final QueryNode query = (QueryNode) getSqlAST();
final boolean hasLimit =
queryParameters.getRowSelection() != null
&& queryParameters.getRowSelection().definesLimits();
final boolean needsDistincting =
( query.getSelectClause().isDistinct() || getEntityGraphQueryHint() != null || hasLimit )
&& containsCollectionFetches();
QueryParameters queryParametersToUse;
if ( hasLimit && containsCollectionFetches() ) {
boolean fail = session.getFactory().getSessionFactoryOptions().isFailOnPaginationOverCollectionFetchEnabled();
if (fail) {
throw new HibernateException("firstResult/maxResults specified with collection fetch. " +
"In memory pagination was about to be applied. " +
"Failing because 'Fail on pagination over collection fetch' is enabled.");
}
else {
LOG.firstOrMaxResultsSpecifiedWithCollectionFetch();
}
RowSelection selection = new RowSelection();
selection.setFetchSize( queryParameters.getRowSelection().getFetchSize() );
selection.setTimeout( queryParameters.getRowSelection().getTimeout() );
queryParametersToUse = queryParameters.createCopyUsing( selection );
}
else {
queryParametersToUse = queryParameters;
}
return queryLoader.reactiveList( (SessionImplementor) session, queryParametersToUse )
.thenApply(results -> {
if ( needsDistincting ) {
int includedCount = -1;
// NOTE : firstRow is zero-based
int first = !hasLimit || queryParameters.getRowSelection().getFirstRow() == null
? 0
: queryParameters.getRowSelection().getFirstRow();
int max = !hasLimit || queryParameters.getRowSelection().getMaxRows() == null
? -1
: queryParameters.getRowSelection().getMaxRows();
List<Object> tmp = new ArrayList<>();
IdentitySet distinction = new IdentitySet();
for ( final Object result : results ) {
if ( !distinction.add( result ) ) {
continue;
}
includedCount++;
if ( includedCount < first ) {
continue;
}
tmp.add( result );
// NOTE : ( max - 1 ) because first is zero-based while max is not...
if ( max >= 0 && ( includedCount - first ) >= ( max - 1 ) ) {
break;
}
}
return tmp;
}
return results;
});
}
@Override
protected String applyLocks(
String sql,
QueryParameters parameters,
Dialect dialect,
List<AfterLoadAction> afterLoadActions) throws QueryException {
// can't cache this stuff either (per-invocation)
// we are given a map of user-alias -> lock mode
// create a new map of sql-alias -> lock mode
final LockOptions lockOptions = parameters.getLockOptions();
if ( lockOptions == null ||
( lockOptions.getLockMode() == LockMode.NONE && lockOptions.getAliasLockCount() == 0 ) ) {
return sql;
}
// user is request locking, lets see if we can apply locking directly to the SQL...
// some dialects wont allow locking with paging...
if ( shouldUseFollowOnLocking( parameters, dialect, afterLoadActions ) ) {
return sql;
}
// there are other conditions we might want to add here, such as checking the result types etc
// but those are better served after we have redone the SQL generation to use ASTs.
// we need both the set of locks and the columns to reference in locks
// as the ultimate output of this section...
final LockOptions locks = new LockOptions( lockOptions.getLockMode() );
final Map<String, String[]> keyColumnNames = dialect.forUpdateOfColumns()
? new HashMap<>()
: null;
locks.setScope( lockOptions.getScope() );
locks.setTimeOut( lockOptions.getTimeOut() );
for ( Map.Entry<String, String> entry : sqlAliasByEntityAlias.entrySet() ) {
final String userAlias = entry.getKey();
final String drivingSqlAlias = entry.getValue();
if ( drivingSqlAlias == null ) {
throw new IllegalArgumentException( "could not locate alias to apply lock mode : " + userAlias );
}
// at this point we have (drivingSqlAlias) the SQL alias of the driving table
// corresponding to the given user alias. However, the driving table is not
// (necessarily) the table against which we want to apply locks. Mainly,
// the exception case here is joined-subclass hierarchies where we instead
// want to apply the lock against the root table (for all other strategies,
// it just happens that driving and root are the same).
final QueryNode select = (QueryNode) queryTranslator.getSqlAST();
final Lockable drivingPersister = (Lockable) select.getFromClause()
.findFromElementByUserOrSqlAlias( userAlias, drivingSqlAlias )
.getQueryable();
final String sqlAlias = drivingPersister.getRootTableAlias( drivingSqlAlias );
final LockMode effectiveLockMode = lockOptions.getEffectiveLockMode( userAlias );
locks.setAliasSpecificLockMode( sqlAlias, effectiveLockMode );
if ( keyColumnNames != null ) {
keyColumnNames.put( sqlAlias, drivingPersister.getRootTableIdentifierColumnNames() );
}
}
// apply the collected locks and columns
return dialect.applyLocksToSql( sql, locks, keyColumnNames );
}
@Override
public List list(SharedSessionContractImplementor session, QueryParameters queryParameters)
throws HibernateException {
// Delegate to the QueryLoader...
errorIfDML();
final QueryNode query = (QueryNode) sqlAst;
final boolean hasLimit = queryParameters.getRowSelection() != null && queryParameters.getRowSelection().definesLimits();
final boolean needsDistincting = (
query.getSelectClause().isDistinct() ||
getEntityGraphQueryHint() != null ||
hasLimit )
&& containsCollectionFetches();
QueryParameters queryParametersToUse;
if ( hasLimit && containsCollectionFetches() ) {
boolean fail = session.getFactory().getSessionFactoryOptions().isFailOnPaginationOverCollectionFetchEnabled();
if (fail) {
throw new HibernateException("firstResult/maxResults specified with collection fetch. " +
"In memory pagination was about to be applied. " +
"Failing because 'Fail on pagination over collection fetch' is enabled.");
}
else {
LOG.firstOrMaxResultsSpecifiedWithCollectionFetch();
}
RowSelection selection = new RowSelection();
selection.setFetchSize( queryParameters.getRowSelection().getFetchSize() );
selection.setTimeout( queryParameters.getRowSelection().getTimeout() );
queryParametersToUse = queryParameters.createCopyUsing( selection );
}
else {
queryParametersToUse = queryParameters;
}
List results = queryLoader.list( session, queryParametersToUse );
if ( needsDistincting ) {
int includedCount = -1;
// NOTE : firstRow is zero-based
int first = !hasLimit || queryParameters.getRowSelection().getFirstRow() == null
? 0
: queryParameters.getRowSelection().getFirstRow();
int max = !hasLimit || queryParameters.getRowSelection().getMaxRows() == null
? -1
: queryParameters.getRowSelection().getMaxRows();
List tmp = new ArrayList();
IdentitySet distinction = new IdentitySet();
for ( final Object result : results ) {
if ( !distinction.add( result ) ) {
continue;
}
includedCount++;
if ( includedCount < first ) {
continue;
}
tmp.add( result );
// NOTE : ( max - 1 ) because first is zero-based while max is not...
if ( max >= 0 && ( includedCount - first ) >= ( max - 1 ) ) {
break;
}
}
results = tmp;
}
return results;
}
@Override
public boolean containsCollectionFetches() {
errorIfDML();
List collectionFetches = ( (QueryNode) sqlAst ).getFromClause().getCollectionFetches();
return collectionFetches != null && collectionFetches.size() > 0;
}
@Override
public void validateScrollability() throws HibernateException {
// Impl Note: allows multiple collection fetches as long as the
// entire fecthed graph still "points back" to a single
// root entity for return
errorIfDML();
final QueryNode query = (QueryNode) sqlAst;
// If there are no collection fetches, then no further checks are needed
List collectionFetches = query.getFromClause().getCollectionFetches();
if ( collectionFetches.isEmpty() ) {
return;
}
// A shallow query is ok (although technically there should be no fetching here...)
if ( isShallowQuery() ) {
return;
}
// Otherwise, we have a non-scalar select with defined collection fetch(es).
// Make sure that there is only a single root entity in the return (no tuples)
if ( getReturnTypes().length > 1 ) {
throw new HibernateException( "cannot scroll with collection fetches and returned tuples" );
}
FromElement owner = null;
for ( Object o : query.getSelectClause().getFromElementsForLoad() ) {
// should be the first, but just to be safe...
final FromElement fromElement = (FromElement) o;
if ( fromElement.getOrigin() == null ) {
owner = fromElement;
break;
}
}
if ( owner == null ) {
throw new HibernateException( "unable to locate collection fetch(es) owner for scrollability checks" );
}
// This is not strictly true. We actually just need to make sure that
// it is ordered by root-entity PK and that that order-by comes before
// any non-root-entity ordering...
AST primaryOrdering = query.getOrderByClause().getFirstChild();
if ( primaryOrdering != null ) {
// TODO : this is a bit dodgy, come up with a better way to check this (plus see above comment)
String [] idColNames = owner.getQueryable().getIdentifierColumnNames();
String expectedPrimaryOrderSeq = String.join(
", ",
StringHelper.qualify( owner.getTableAlias(), idColNames )
);
if ( !primaryOrdering.getText().startsWith( expectedPrimaryOrderSeq ) ) {
throw new HibernateException( "cannot scroll results with collection fetches which are not ordered primarily by the root entity's PK" );
}
}
}