Package org.hibernate.loader.internal

Source Code of org.hibernate.loader.internal.ResultSetProcessingContextImpl$HydratedEntityRegistration

/*
* 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.internal;

import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.jboss.logging.Logger;

import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.StaleObjectStateException;
import org.hibernate.WrongClassException;
import org.hibernate.collection.spi.PersistentCollection;
import org.hibernate.engine.internal.TwoPhaseLoad;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.EntityUniqueKey;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.SubselectFetch;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.PostLoadEvent;
import org.hibernate.event.spi.PreLoadEvent;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.loader.EntityAliases;
import org.hibernate.loader.plan.spi.CollectionFetch;
import org.hibernate.loader.plan.spi.CollectionReturn;
import org.hibernate.loader.plan.spi.EntityReference;
import org.hibernate.loader.plan.spi.LoadPlan;
import org.hibernate.loader.plan.spi.visit.LoadPlanVisitationStrategyAdapter;
import org.hibernate.loader.plan.spi.visit.LoadPlanVisitor;
import org.hibernate.loader.spi.AfterLoadAction;
import org.hibernate.loader.spi.LoadQueryAliasResolutionContext;
import org.hibernate.loader.spi.NamedParameterContext;
import org.hibernate.loader.spi.ResultSetProcessingContext;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.UniqueKeyLoadable;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
import org.hibernate.type.VersionType;

/**
* @author Steve Ebersole
*/
public class ResultSetProcessingContextImpl implements ResultSetProcessingContext {
  private static final Logger LOG = Logger.getLogger( ResultSetProcessingContextImpl.class );

  private final ResultSet resultSet;
  private final SessionImplementor session;
  private final LoadPlan loadPlan;
  private final boolean readOnly;
  private final QueryParameters queryParameters;
  private final NamedParameterContext namedParameterContext;
  private final LoadQueryAliasResolutionContext aliasResolutionContext;
  private final boolean hadSubselectFetches;

  private final EntityKey dictatedRootEntityKey;

  private List<HydratedEntityRegistration> currentRowHydratedEntityRegistrationList;

  private Map<EntityPersister,Set<EntityKey>> subselectLoadableEntityKeyMap;
  private List<HydratedEntityRegistration> hydratedEntityRegistrationList;

  public ResultSetProcessingContextImpl(
      ResultSet resultSet,
      SessionImplementor session,
      LoadPlan loadPlan,
      boolean readOnly,
      boolean useOptionalEntityKey,
      QueryParameters queryParameters,
      NamedParameterContext namedParameterContext,
      LoadQueryAliasResolutionContext aliasResolutionContext,
      boolean hadSubselectFetches) {
    this.resultSet = resultSet;
    this.session = session;
    this.loadPlan = loadPlan;
    this.readOnly = readOnly;
    this.queryParameters = queryParameters;
    this.namedParameterContext = namedParameterContext;
    this.aliasResolutionContext = aliasResolutionContext;
    this.hadSubselectFetches = hadSubselectFetches;

    if ( useOptionalEntityKey ) {
      this.dictatedRootEntityKey = ResultSetProcessorHelper.getOptionalObjectKey( queryParameters, session );
      if ( this.dictatedRootEntityKey == null ) {
        throw new HibernateException( "Unable to resolve optional entity-key" );
      }
    }
    else {
      this.dictatedRootEntityKey = null;
    }
  }

  @Override
  public SessionImplementor getSession() {
    return session;
  }

  @Override
  public QueryParameters getQueryParameters() {
    return queryParameters;
  }

  @Override
  public EntityKey getDictatedRootEntityKey() {
    return dictatedRootEntityKey;
  }

  private Map<EntityReference,IdentifierResolutionContext> identifierResolutionContextMap;

  @Override
  public IdentifierResolutionContext getIdentifierResolutionContext(final EntityReference entityReference) {
    if ( identifierResolutionContextMap == null ) {
      identifierResolutionContextMap = new HashMap<EntityReference, IdentifierResolutionContext>();
    }
    IdentifierResolutionContext context = identifierResolutionContextMap.get( entityReference );
    if ( context == null ) {
      context = new IdentifierResolutionContext() {
        private Object hydratedForm;
        private EntityKey entityKey;

        @Override
        public EntityReference getEntityReference() {
          return entityReference;
        }

        @Override
        public void registerHydratedForm(Object hydratedForm) {
          if ( this.hydratedForm != null ) {
            // this could be bad...
          }
          this.hydratedForm = hydratedForm;
        }

        @Override
        public Object getHydratedForm() {
          return hydratedForm;
        }

        @Override
        public void registerEntityKey(EntityKey entityKey) {
          if ( this.entityKey != null ) {
            // again, could be trouble...
          }
          this.entityKey = entityKey;
        }

        @Override
        public EntityKey getEntityKey() {
          return entityKey;
        }
      };
      identifierResolutionContextMap.put( entityReference, context );
    }

    return context;
  }

  @Override
  public Set<IdentifierResolutionContext> getIdentifierResolutionContexts() {
    return Collections.unmodifiableSet(
        new HashSet<IdentifierResolutionContext>( identifierResolutionContextMap.values() )
    );
  }

  @Override
  public LoadQueryAliasResolutionContext getLoadQueryAliasResolutionContext() {
    return aliasResolutionContext;
  }

  @Override
  public void checkVersion(
      ResultSet resultSet,
      EntityPersister persister,
      EntityAliases entityAliases,
      EntityKey entityKey,
      Object entityInstance) {
    final Object version = session.getPersistenceContext().getEntry( entityInstance ).getVersion();

    if ( version != null ) {
      //null version means the object is in the process of being loaded somewhere else in the ResultSet
      VersionType versionType = persister.getVersionType();
      final Object currentVersion;
      try {
        currentVersion = versionType.nullSafeGet(
            resultSet,
            entityAliases.getSuffixedVersionAliases(),
            session,
            null
        );
      }
      catch (SQLException e) {
        throw getSession().getFactory().getJdbcServices().getSqlExceptionHelper().convert(
            e,
            "Could not read version value from result set"
        );
      }

      if ( !versionType.isEqual( version, currentVersion ) ) {
        if ( session.getFactory().getStatistics().isStatisticsEnabled() ) {
          session.getFactory().getStatisticsImplementor().optimisticFailure( persister.getEntityName() );
        }
        throw new StaleObjectStateException( persister.getEntityName(), entityKey.getIdentifier() );
      }
    }
  }

  @Override
  public String getConcreteEntityTypeName(
      final ResultSet rs,
      final EntityPersister persister,
      final EntityAliases entityAliases,
      final EntityKey entityKey) {

    final Loadable loadable = (Loadable) persister;
    if ( ! loadable.hasSubclasses() ) {
      return persister.getEntityName();
    }

    final Object discriminatorValue;
    try {
      discriminatorValue = loadable.getDiscriminatorType().nullSafeGet(
          rs,
          entityAliases.getSuffixedDiscriminatorAlias(),
          session,
          null
      );
    }
    catch (SQLException e) {
      throw getSession().getFactory().getJdbcServices().getSqlExceptionHelper().convert(
          e,
          "Could not read discriminator value from ResultSet"
      );
    }

    final String result = loadable.getSubclassForDiscriminatorValue( discriminatorValue );

    if ( result == null ) {
      // whoops! we got an instance of another class hierarchy branch
      throw new WrongClassException(
          "Discriminator: " + discriminatorValue,
          entityKey.getIdentifier(),
          persister.getEntityName()
      );
    }

    return result;
  }

  @Override
  public Object resolveEntityKey(EntityKey entityKey, EntityKeyResolutionContext entityKeyContext) {
    final Object existing = getSession().getEntityUsingInterceptor( entityKey );

    if ( existing != null ) {
      if ( !entityKeyContext.getEntityPersister().isInstance( existing ) ) {
        throw new WrongClassException(
            "loaded object was of wrong class " + existing.getClass(),
            entityKey.getIdentifier(),
            entityKeyContext.getEntityPersister().getEntityName()
        );
      }

      final LockMode requestedLockMode = entityKeyContext.getLockMode() == null
          ? LockMode.NONE
          : entityKeyContext.getLockMode();

      if ( requestedLockMode != LockMode.NONE ) {
        final LockMode currentLockMode = getSession().getPersistenceContext().getEntry( existing ).getLockMode();
        final boolean isVersionCheckNeeded = entityKeyContext.getEntityPersister().isVersioned()
            && currentLockMode.lessThan( requestedLockMode );

        // we don't need to worry about existing version being uninitialized because this block isn't called
        // by a re-entrant load (re-entrant loads *always* have lock mode NONE)
        if ( isVersionCheckNeeded ) {
          //we only check the version when *upgrading* lock modes
          checkVersion(
              resultSet,
              entityKeyContext.getEntityPersister(),
              aliasResolutionContext.resolveEntityColumnAliases( entityKeyContext.getEntityReference() ),
              entityKey,
              existing
          );
          //we need to upgrade the lock mode to the mode requested
          getSession().getPersistenceContext().getEntry( existing ).setLockMode( requestedLockMode );
        }
      }

      return existing;
    }
    else {
      final String concreteEntityTypeName = getConcreteEntityTypeName(
          resultSet,
          entityKeyContext.getEntityPersister(),
          aliasResolutionContext.resolveEntityColumnAliases( entityKeyContext.getEntityReference() ),
          entityKey
      );

      final Object entityInstance = getSession().instantiate(
          concreteEntityTypeName,
          entityKey.getIdentifier()
      );

      //need to hydrate it.

      // grab its state from the ResultSet and keep it in the Session
      // (but don't yet initialize the object itself)
      // note that we acquire LockMode.READ even if it was not requested
      final LockMode requestedLockMode = entityKeyContext.getLockMode() == null
          ? LockMode.NONE
          : entityKeyContext.getLockMode();
      final LockMode acquiredLockMode = requestedLockMode == LockMode.NONE
          ? LockMode.READ
          : requestedLockMode;

      loadFromResultSet(
          resultSet,
          entityInstance,
          concreteEntityTypeName,
          entityKey,
          aliasResolutionContext.resolveEntityColumnAliases( entityKeyContext.getEntityReference() ),
          acquiredLockMode,
          entityKeyContext.getEntityPersister(),
          true,
          entityKeyContext.getEntityPersister().getEntityMetamodel().getEntityType()
      );

      // materialize associations (and initialize the object) later
      registerHydratedEntity( entityKeyContext.getEntityPersister(), entityKey, entityInstance );

      return entityInstance;
    }
  }

  @Override
  public void loadFromResultSet(
      ResultSet resultSet,
      Object entityInstance,
      String concreteEntityTypeName,
      EntityKey entityKey,
      EntityAliases entityAliases,
      LockMode acquiredLockMode,
      EntityPersister rootPersister,
      boolean eagerFetch,
      EntityType associationType) {

    final Serializable id = entityKey.getIdentifier();

    // Get the persister for the _subclass_
    final Loadable persister = (Loadable) getSession().getFactory().getEntityPersister( concreteEntityTypeName );

    if ( LOG.isTraceEnabled() ) {
      LOG.tracev(
          "Initializing object from ResultSet: {0}",
          MessageHelper.infoString(
              persister,
              id,
              getSession().getFactory()
          )
      );
    }

    // add temp entry so that the next step is circular-reference
    // safe - only needed because some types don't take proper
    // advantage of two-phase-load (esp. components)
    TwoPhaseLoad.addUninitializedEntity(
        entityKey,
        entityInstance,
        persister,
        acquiredLockMode,
        !eagerFetch,
        session
    );

    // This is not very nice (and quite slow):
    final String[][] cols = persister == rootPersister ?
        entityAliases.getSuffixedPropertyAliases() :
        entityAliases.getSuffixedPropertyAliases(persister);

    final Object[] values;
    try {
      values = persister.hydrate(
          resultSet,
          id,
          entityInstance,
          (Loadable) rootPersister,
          cols,
          eagerFetch,
          session
      );
    }
    catch (SQLException e) {
      throw getSession().getFactory().getJdbcServices().getSqlExceptionHelper().convert(
          e,
          "Could not read entity state from ResultSet : " + entityKey
      );
    }

    final Object rowId;
    try {
      rowId = persister.hasRowId() ? resultSet.getObject( entityAliases.getRowIdAlias() ) : null;
    }
    catch (SQLException e) {
      throw getSession().getFactory().getJdbcServices().getSqlExceptionHelper().convert(
          e,
          "Could not read entity row-id from ResultSet : " + entityKey
      );
    }

    if ( associationType != null ) {
      String ukName = associationType.getRHSUniqueKeyPropertyName();
      if ( ukName != null ) {
        final int index = ( (UniqueKeyLoadable) persister ).getPropertyIndex( ukName );
        final Type type = persister.getPropertyTypes()[index];

        // polymorphism not really handled completely correctly,
        // perhaps...well, actually its ok, assuming that the
        // entity name used in the lookup is the same as the
        // the one used here, which it will be

        EntityUniqueKey euk = new EntityUniqueKey(
            rootPersister.getEntityName(), //polymorphism comment above
            ukName,
            type.semiResolve( values[index], session, entityInstance ),
            type,
            persister.getEntityMode(),
            session.getFactory()
        );
        session.getPersistenceContext().addEntity( euk, entityInstance );
      }
    }

    TwoPhaseLoad.postHydrate(
        persister,
        id,
        values,
        rowId,
        entityInstance,
        acquiredLockMode,
        !eagerFetch,
        session
    );

  }

  public void readCollectionElements(final Object[] row) {
      LoadPlanVisitor.visit(
          loadPlan,
          new LoadPlanVisitationStrategyAdapter() {
            @Override
            public void handleCollectionReturn(CollectionReturn rootCollectionReturn) {
              readCollectionElement(
                  null,
                  null,
                  rootCollectionReturn.getCollectionPersister(),
                  aliasResolutionContext.resolveCollectionColumnAliases( rootCollectionReturn ),
                  resultSet,
                  session
              );
            }

            @Override
            public void startingCollectionFetch(CollectionFetch collectionFetch) {
              // TODO: determine which element is the owner.
              final Object owner = row[ 0 ];
              readCollectionElement(
                  owner,
                  collectionFetch.getCollectionPersister().getCollectionType().getKeyOfOwner( owner, session ),
                  collectionFetch.getCollectionPersister(),
                  aliasResolutionContext.resolveCollectionColumnAliases( collectionFetch ),
                  resultSet,
                  session
              );
            }

            private void readCollectionElement(
                final Object optionalOwner,
                final Serializable optionalKey,
                final CollectionPersister persister,
                final CollectionAliases descriptor,
                final ResultSet rs,
                final SessionImplementor session) {

              try {
                final PersistenceContext persistenceContext = session.getPersistenceContext();

                final Serializable collectionRowKey = (Serializable) persister.readKey(
                    rs,
                    descriptor.getSuffixedKeyAliases(),
                    session
                );

                if ( collectionRowKey != null ) {
                  // we found a collection element in the result set

                  if ( LOG.isDebugEnabled() ) {
                    LOG.debugf( "Found row of collection: %s",
                        MessageHelper.collectionInfoString( persister, collectionRowKey, session.getFactory() ) );
                  }

                  Object owner = optionalOwner;
                  if ( owner == null ) {
                    owner = persistenceContext.getCollectionOwner( collectionRowKey, persister );
                    if ( owner == null ) {
                      //TODO: This is assertion is disabled because there is a bug that means the
                      //    original owner of a transient, uninitialized collection is not known
                      //    if the collection is re-referenced by a different object associated
                      //    with the current Session
                      //throw new AssertionFailure("bug loading unowned collection");
                    }
                  }

                  PersistentCollection rowCollection = persistenceContext.getLoadContexts()
                      .getCollectionLoadContext( rs )
                      .getLoadingCollection( persister, collectionRowKey );

                  if ( rowCollection != null ) {
                    rowCollection.readFrom( rs, persister, descriptor, owner );
                  }

                }
                else if ( optionalKey != null ) {
                  // we did not find a collection element in the result set, so we
                  // ensure that a collection is created with the owner's identifier,
                  // since what we have is an empty collection

                  if ( LOG.isDebugEnabled() ) {
                    LOG.debugf( "Result set contains (possibly empty) collection: %s",
                        MessageHelper.collectionInfoString( persister, optionalKey, session.getFactory() ) );
                  }

                  persistenceContext.getLoadContexts()
                      .getCollectionLoadContext( rs )
                      .getLoadingCollection( persister, optionalKey ); // handle empty collection

                }

                // else no collection element, but also no owner
              }
              catch ( SQLException sqle ) {
                // TODO: would be nice to have the SQL string that failed...
                throw session.getFactory().getSQLExceptionHelper().convert(
                    sqle,
                    "could not read next row of results"
                );
              }
            }

          }
      );
  }

  @Override
  public void registerHydratedEntity(EntityPersister persister, EntityKey entityKey, Object entityInstance) {
    if ( currentRowHydratedEntityRegistrationList == null ) {
      currentRowHydratedEntityRegistrationList = new ArrayList<HydratedEntityRegistration>();
    }
    currentRowHydratedEntityRegistrationList.add( new HydratedEntityRegistration( persister, entityKey, entityInstance ) );
  }

  /**
   * Package-protected
   */
  void finishUpRow() {
    if ( currentRowHydratedEntityRegistrationList == null ) {
      return;
    }


    // managing the running list of registrations ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if ( hydratedEntityRegistrationList == null ) {
      hydratedEntityRegistrationList = new ArrayList<HydratedEntityRegistration>();
    }
    hydratedEntityRegistrationList.addAll( currentRowHydratedEntityRegistrationList );


    // managing the map forms needed for subselect fetch generation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    if ( hadSubselectFetches ) {
      if ( subselectLoadableEntityKeyMap == null ) {
        subselectLoadableEntityKeyMap = new HashMap<EntityPersister, Set<EntityKey>>();
      }
      for ( HydratedEntityRegistration registration : currentRowHydratedEntityRegistrationList ) {
        Set<EntityKey> entityKeys = subselectLoadableEntityKeyMap.get( registration.persister );
        if ( entityKeys == null ) {
          entityKeys = new HashSet<EntityKey>();
          subselectLoadableEntityKeyMap.put( registration.persister, entityKeys );
        }
        entityKeys.add( registration.key );
      }
    }

    // release the currentRowHydratedEntityRegistrationList entries
    currentRowHydratedEntityRegistrationList.clear();
  }

  /**
   * Package-protected
   *
   * @param afterLoadActionList List of after-load actions to perform
   */
  void finishUp(List<AfterLoadAction> afterLoadActionList) {
    initializeEntitiesAndCollections( afterLoadActionList );
    createSubselects();

    if ( hydratedEntityRegistrationList != null ) {
      hydratedEntityRegistrationList.clear();
      hydratedEntityRegistrationList = null;
    }

    if ( subselectLoadableEntityKeyMap != null ) {
      subselectLoadableEntityKeyMap.clear();
      subselectLoadableEntityKeyMap = null;
    }
  }

  private void initializeEntitiesAndCollections(List<AfterLoadAction> afterLoadActionList) {
    // for arrays, we should end the collection load before resolving the entities, since the
    // actual array instances are not instantiated during loading
    finishLoadingArrays();


    // IMPORTANT: reuse the same event instances for performance!
    final PreLoadEvent preLoadEvent;
    final PostLoadEvent postLoadEvent;
    if ( session.isEventSource() ) {
      preLoadEvent = new PreLoadEvent( (EventSource) session );
      postLoadEvent = new PostLoadEvent( (EventSource) session );
    }
    else {
      preLoadEvent = null;
      postLoadEvent = null;
    }

    // now finish loading the entities (2-phase load)
    performTwoPhaseLoad( preLoadEvent );

    // now we can finalize loading collections
    finishLoadingCollections();

    // finally, perform post-load operations
    postLoad( postLoadEvent, afterLoadActionList );
  }

  private void finishLoadingArrays() {
    LoadPlanVisitor.visit(
        loadPlan,
        new LoadPlanVisitationStrategyAdapter() {
          @Override
          public void handleCollectionReturn(CollectionReturn rootCollectionReturn) {
            endLoadingArray( rootCollectionReturn.getCollectionPersister() );
          }

          @Override
          public void startingCollectionFetch(CollectionFetch collectionFetch) {
            endLoadingArray( collectionFetch.getCollectionPersister() );
          }

          private void endLoadingArray(CollectionPersister persister) {
            if ( persister.isArray() ) {
              session.getPersistenceContext()
                  .getLoadContexts()
                  .getCollectionLoadContext( resultSet )
                  .endLoadingCollections( persister );
            }
          }
        }
    );
  }

  private void performTwoPhaseLoad(PreLoadEvent preLoadEvent) {
    final int numberOfHydratedObjects = hydratedEntityRegistrationList == null
        ? 0
        : hydratedEntityRegistrationList.size();
    LOG.tracev( "Total objects hydrated: {0}", numberOfHydratedObjects );

    if ( hydratedEntityRegistrationList == null ) {
      return;
    }

    for ( HydratedEntityRegistration registration : hydratedEntityRegistrationList ) {
      TwoPhaseLoad.initializeEntity( registration.instance, readOnly, session, preLoadEvent );
    }
  }

  private void finishLoadingCollections() {
    LoadPlanVisitor.visit(
        loadPlan,
        new LoadPlanVisitationStrategyAdapter() {
          @Override
          public void handleCollectionReturn(CollectionReturn rootCollectionReturn) {
            endLoadingCollection( rootCollectionReturn.getCollectionPersister() );
          }

          @Override
          public void startingCollectionFetch(CollectionFetch collectionFetch) {
            endLoadingCollection( collectionFetch.getCollectionPersister() );
          }

          private void endLoadingCollection(CollectionPersister persister) {
            if ( ! persister.isArray() ) {
              session.getPersistenceContext()
                  .getLoadContexts()
                  .getCollectionLoadContext( resultSet )
                  .endLoadingCollections( persister );
            }
          }
        }
    );
  }

  private void postLoad(PostLoadEvent postLoadEvent, List<AfterLoadAction> afterLoadActionList) {
    // Until this entire method is refactored w/ polymorphism, postLoad was
    // split off from initializeEntity.  It *must* occur after
    // endCollectionLoad to ensure the collection is in the
    // persistence context.
    if ( hydratedEntityRegistrationList == null ) {
      return;
    }

    for ( HydratedEntityRegistration registration : hydratedEntityRegistrationList ) {
      TwoPhaseLoad.postLoad( registration.instance, session, postLoadEvent );
      if ( afterLoadActionList != null ) {
        for ( AfterLoadAction afterLoadAction : afterLoadActionList ) {
          afterLoadAction.afterLoad( session, registration.instance, (Loadable) registration.persister );
        }
      }
    }
  }

  private void createSubselects() {
    if ( subselectLoadableEntityKeyMap == null || subselectLoadableEntityKeyMap.size() <= 1 ) {
      // if we only returned one entity, query by key is more efficient; so do nothing here
      return;
    }

    final Map<String, int[]> namedParameterLocMap =
        ResultSetProcessorHelper.buildNamedParameterLocMap( queryParameters, namedParameterContext );

    for ( Map.Entry<EntityPersister, Set<EntityKey>> entry : subselectLoadableEntityKeyMap.entrySet() ) {
      if ( ! entry.getKey().hasSubselectLoadableCollections() ) {
        continue;
      }

      SubselectFetch subselectFetch = new SubselectFetch(
          //getSQLString(),
          null, // aliases[i],
          (Loadable) entry.getKey(),
          queryParameters,
          entry.getValue(),
          namedParameterLocMap
      );

      for ( EntityKey key : entry.getValue() ) {
        session.getPersistenceContext().getBatchFetchQueue().addSubselect( key, subselectFetch );
      }

    }
  }

  private static class HydratedEntityRegistration {
    private final EntityPersister persister;
    private final EntityKey key;
    private final Object instance;

    private HydratedEntityRegistration(EntityPersister persister, EntityKey key, Object instance) {
      this.persister = persister;
      this.key = key;
      this.instance = instance;
    }
  }
}
TOP

Related Classes of org.hibernate.loader.internal.ResultSetProcessingContextImpl$HydratedEntityRegistration

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.