package org.hibernate.loader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.hibernate.FetchMode;
import org.hibernate.LockOptions;
import org.hibernate.MappingException;
import org.hibernate.engine.profile.Fetch;
import org.hibernate.engine.profile.FetchProfile;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.sql.JoinFragment;
import org.hibernate.sql.Select;
import org.hibernate.type.AssociationType;
public abstract class AbstractEntityJoinWalker extends JoinWalker {
private final OuterJoinLoadable persister;
private final String alias;
public AbstractEntityJoinWalker(
OuterJoinLoadable persister,
SessionFactoryImplementor factory,
LoadQueryInfluencers loadQueryInfluencers) {
this( persister, factory, loadQueryInfluencers, null );
}
public AbstractEntityJoinWalker(
OuterJoinLoadable persister,
SessionFactoryImplementor factory,
LoadQueryInfluencers loadQueryInfluencers,
String alias) {
super( factory, loadQueryInfluencers );
this.persister = persister;
this.alias = ( alias == null ) ? generateRootAlias( persister.getEntityName() ) : alias;
}
protected final void initAll(
final String whereString,
final String orderByString,
final LockOptions lockOptions) throws MappingException {
initAll( whereString, orderByString, lockOptions, AssociationInitCallback.NO_CALLBACK );
}
protected final void initAll(
final String whereString,
final String orderByString,
final LockOptions lockOptions,
final AssociationInitCallback callback) throws MappingException {
walkEntityTree( persister, getAlias() );
List allAssociations = new ArrayList();
allAssociations.addAll( associations );
allAssociations.add( OuterJoinableAssociation.createRoot( persister.getEntityType(), alias, getFactory() ) );
initPersisters( allAssociations, lockOptions, callback );
initStatementString( whereString, orderByString, lockOptions );
}
protected final void initProjection(
final String projectionString,
final String whereString,
final String orderByString,
final String groupByString,
final LockOptions lockOptions) throws MappingException {
walkEntityTree( persister, getAlias() );
persisters = new Loadable[0];
initStatementString(projectionString, whereString, orderByString, groupByString, lockOptions);
}
private void initStatementString(
final String condition,
final String orderBy,
final LockOptions lockOptions) throws MappingException {
initStatementString(null, condition, orderBy, "", lockOptions);
}
private void initStatementString(
final String projection,
final String condition,
final String orderBy,
final String groupBy,
final LockOptions lockOptions) throws MappingException {
final int joins = countEntityPersisters( associations );
suffixes = BasicLoader.generateSuffixes( joins + 1 );
JoinFragment ojf = mergeOuterJoins( associations );
Select select = new Select( getDialect() )
.setLockOptions( lockOptions )
.setSelectClause(
projection == null ?
persister.selectFragment( alias, suffixes[joins] ) + selectString( associations ) :
projection
)
.setFromClause(
getDialect().appendLockHint( lockOptions, persister.fromTableFragment( alias ) ) +
persister.fromJoinFragment( alias, true, true )
)
.setWhereClause( condition )
.setOuterJoins(
ojf.toFromFragmentString(),
ojf.toWhereFragmentString() + getWhereFragment()
)
.setOrderByClause( orderBy( associations, orderBy ) )
.setGroupByClause( groupBy );
if ( getFactory().getSessionFactoryOptions().isCommentsEnabled() ) {
select.setComment( getComment() );
}
sql = select.toStatementString();
}
protected String getWhereFragment() throws MappingException {
return persister.whereJoinFragment(alias, true, true);
}
protected boolean isJoinedFetchEnabled(AssociationType type, FetchMode config, CascadeStyle cascadeStyle) {
return isJoinedFetchEnabledInMapping( config, type );
}
protected final boolean isJoinFetchEnabledByProfile(OuterJoinLoadable persister, PropertyPath path, int propertyNumber) {
if ( !getLoadQueryInfluencers().hasEnabledFetchProfiles() ) {
return false;
}
final String fullPath = path.getFullPath();
String rootPropertyName = persister.getSubclassPropertyName( propertyNumber );
int pos = fullPath.lastIndexOf( rootPropertyName );
String relativePropertyPath = pos >= 0
? fullPath.substring( pos )
: rootPropertyName;
String fetchRole = persister.getEntityName() + "." + relativePropertyPath;
for ( String profileName : getLoadQueryInfluencers().getEnabledFetchProfileNames() ) {
final FetchProfile profile = getFactory().getFetchProfile( profileName );
final Fetch fetch = profile.getFetchByRole( fetchRole );
if ( fetch != null && Fetch.Style.JOIN == fetch.getStyle() ) {
return true;
}
}
return false;
}
public abstract String ();
@Override
protected boolean isDuplicateAssociation(final String foreignKeyTable, final String[] foreignKeyColumns) {
final boolean isSameJoin =
persister.getTableName().equals( foreignKeyTable ) &&
Arrays.equals( foreignKeyColumns, persister.getKeyColumnNames() );
return isSameJoin ||
super.isDuplicateAssociation(foreignKeyTable, foreignKeyColumns);
}
public final Loadable getPersister() {
return persister;
}
public final String getAlias() {
return alias;
}
@Override
protected String orderBy(final List associations, final String orderBy) {
return mergeOrderings( orderBy, orderBy( associations ) );
}
public String toString() {
return getClass().getName() + '(' + getPersister().getEntityName() + ')';
}
}