Package org.hibernate.loader.plan.exec.query.internal

Source Code of org.hibernate.loader.plan.exec.query.internal.EntityLoadQueryBuilderImpl

/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors.  All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA  02110-1301  USA
*/
package org.hibernate.loader.plan.exec.query.internal;

import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.loader.plan.exec.internal.Helper;
import org.hibernate.loader.plan.exec.internal.LoadQueryBuilderHelper;
import org.hibernate.loader.plan.exec.process.internal.CollectionReferenceReader;
import org.hibernate.loader.plan.exec.process.internal.EntityReferenceReader;
import org.hibernate.loader.plan.exec.query.spi.EntityLoadQueryBuilder;
import org.hibernate.loader.plan.exec.query.spi.QueryBuildingParameters;
import org.hibernate.loader.plan.exec.spi.AliasResolutionContext;
import org.hibernate.loader.plan.exec.spi.ReaderCollector;
import org.hibernate.loader.plan.exec.spi.RowReader;
import org.hibernate.loader.plan.spi.EntityReturn;
import org.hibernate.loader.plan.spi.LoadPlan;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.sql.ConditionFragment;
import org.hibernate.sql.DisjunctionFragment;
import org.hibernate.sql.InFragment;

/**
* @author Steve Ebersole
*/
public class EntityLoadQueryBuilderImpl implements EntityLoadQueryBuilder {
  /**
   * Singleton access
   */
  public static final EntityLoadQueryBuilderImpl INSTANCE = new EntityLoadQueryBuilderImpl();

  @Override
  public String generateSql(
      LoadPlan loadPlan,
      SessionFactoryImplementor factory,
      QueryBuildingParameters buildingParameters,
      AliasResolutionContext aliasResolutionContext) {
    final EntityReturn rootReturn = Helper.INSTANCE.extractRootReturn( loadPlan, EntityReturn.class );

    return generateSql(
        ( (Queryable) rootReturn.getEntityPersister() ).getKeyColumnNames(),
        rootReturn,
        factory,
        buildingParameters,
        aliasResolutionContext
    );
  }

  @Override
  public String generateSql(
      String[] keyColumnNames,
      LoadPlan loadPlan,
      SessionFactoryImplementor factory,
      QueryBuildingParameters buildingParameters,
      AliasResolutionContext aliasResolutionContext) {
    final EntityReturn rootReturn = Helper.INSTANCE.extractRootReturn( loadPlan, EntityReturn.class );

    final String[] keyColumnNamesToUse = keyColumnNames != null
        ? keyColumnNames
        : ( (Queryable) rootReturn.getEntityPersister() ).getIdentifierColumnNames();

    return generateSql(
        keyColumnNamesToUse,
        rootReturn,
        factory,
        buildingParameters,
        aliasResolutionContext
    );
  }

  protected String generateSql(
      String[] keyColumnNames,
      EntityReturn rootReturn,
      SessionFactoryImplementor factory,
      QueryBuildingParameters buildingParameters,
      AliasResolutionContext aliasResolutionContext) {
    final SelectStatementBuilder select = new SelectStatementBuilder( factory.getDialect() );

    // apply root entity return specifics
    applyRootReturnSpecifics(
        select,
        keyColumnNames,
        rootReturn,
        factory,
        buildingParameters,
        aliasResolutionContext
    );

    LoadQueryBuilderHelper.applyJoinFetches(
        select,
        factory,
        rootReturn,
        buildingParameters,
        aliasResolutionContext,
        new ReaderCollector() {

          @Override
          public void addReader(CollectionReferenceReader collectionReferenceReader) {
          }

          @Override
          public void addReader(EntityReferenceReader entityReferenceReader) {
          }
        }
    );

    return select.toStatementString();
  }

  protected void applyRootReturnSpecifics(
      SelectStatementBuilder select,
      String[] keyColumnNames,
      EntityReturn rootReturn,
      SessionFactoryImplementor factory,
      QueryBuildingParameters buildingParameters,
      AliasResolutionContext aliasResolutionContext) {
    final String rootAlias = aliasResolutionContext.resolveAliases( rootReturn ).getTableAlias();
    final OuterJoinLoadable rootLoadable = (OuterJoinLoadable) rootReturn.getEntityPersister();
    final Queryable rootQueryable = (Queryable) rootReturn.getEntityPersister();

    applyKeyRestriction( select, rootAlias, keyColumnNames, buildingParameters.getBatchSize() );
    select.appendRestrictions(
        rootQueryable.filterFragment(
            rootAlias,
            buildingParameters.getQueryInfluencers().getEnabledFilters()
        )
    );
    select.appendRestrictions( rootLoadable.whereJoinFragment( rootAlias, true, true ) );
    select.appendSelectClauseFragment(
        rootLoadable.selectFragment(
            rootAlias,
            aliasResolutionContext.resolveAliases( rootReturn ).getColumnAliases().getSuffix()
        )
    );

    final String fromTableFragment;
    if ( buildingParameters.getLockOptions() != null ) {
      fromTableFragment = factory.getDialect().appendLockHint(
          buildingParameters.getLockOptions(),
          rootLoadable.fromTableFragment( rootAlias )
      );
      select.setLockOptions( buildingParameters.getLockOptions() );
    }
    else if ( buildingParameters.getLockMode() != null ) {
      fromTableFragment = factory.getDialect().appendLockHint(
          buildingParameters.getLockMode(),
          rootLoadable.fromTableFragment( rootAlias )
      );
      select.setLockMode( buildingParameters.getLockMode() );
    }
    else {
      fromTableFragment = rootLoadable.fromTableFragment( rootAlias );
    }
    select.appendFromClauseFragment( fromTableFragment + rootLoadable.fromJoinFragment( rootAlias, true, true ) );
  }

  private void applyKeyRestriction(SelectStatementBuilder select, String alias, String[] keyColumnNames, int batchSize) {
    if ( keyColumnNames.length==1 ) {
      // NOT A COMPOSITE KEY
      //     for batching, use "foo in (?, ?, ?)" for batching
      //    for no batching, use "foo = ?"
      // (that distinction is handled inside InFragment)
      final InFragment in = new InFragment().setColumn( alias, keyColumnNames[0] );
      for ( int i = 0; i < batchSize; i++ ) {
        in.addValue( "?" );
      }
      select.appendRestrictions( in.toFragmentString() );
    }
    else {
      // A COMPOSITE KEY...
      final ConditionFragment keyRestrictionBuilder = new ConditionFragment()
          .setTableAlias( alias )
          .setCondition( keyColumnNames, "?" );
      final String keyRestrictionFragment = keyRestrictionBuilder.toFragmentString();

      StringBuilder restrictions = new StringBuilder();
      if ( batchSize==1 ) {
        // for no batching, use "foo = ? and bar = ?"
        restrictions.append( keyRestrictionFragment );
      }
      else {
        // for batching, use "( (foo = ? and bar = ?) or (foo = ? and bar = ?) )"
        restrictions.append( '(' );
        DisjunctionFragment df = new DisjunctionFragment();
        for ( int i=0; i<batchSize; i++ ) {
          df.addCondition( keyRestrictionFragment );
        }
        restrictions.append( df.toFragmentString() );
        restrictions.append( ')' );
      }
      select.appendRestrictions( restrictions.toString() );
    }
  }
}
TOP

Related Classes of org.hibernate.loader.plan.exec.query.internal.EntityLoadQueryBuilderImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.