outerjoinloader.java

来自「hibernate-3.0.5 中文文档」· Java 代码 · 共 989 行 · 第 1/2 页

JAVA
989
字号
					visitedAssociations,					persister.getTableName(),					lhsColumns,					propertyNullability==null || propertyNullability[i],					currentDepth				);				addAssociationToJoinTreeIfNecessary(					associationType,					aliasedLhsColumns,					alias,					associations,					visitedAssociations,					subpath,					currentDepth,					joinType				);			}			else if ( types[i].isComponentType() ) {				String subpath = subPath( path, propertyNames[i] );				walkCompositeElementTree(					(AbstractComponentType) types[i],					lhsColumns,					persister,					alias,					associations,					visitedAssociations,					subpath,					currentDepth				);			}			begin+=length;		}	}	/**	 * Does the mapping, and Hibernate default semantics, specify that	 * this association should be fetched by outer joining	 */	protected boolean isJoinedFetchEnabledInMapping(FetchMode config, AssociationType type) 	throws MappingException {		if ( !type.isEntityType() && !type.isCollectionType() ) {			return false;		}		else {			if (config==FetchMode.JOIN) return true;			if (config==FetchMode.SELECT) return false;			if ( type.isEntityType() ) {				//TODO: look at the owning property and check that it 				//      isn't lazy (by instrumentation)				EntityType entityType =(EntityType) type;				EntityPersister persister = getFactory().getEntityPersister( entityType.getAssociatedEntityName() );				return !persister.hasProxy();			}			else {				return false;			}		}	}	/**	 * Add on association (one-to-one, many-to-one, or a collection) to a list 	 * of associations to be fetched by outerjoin (if necessary)	 */	private void addAssociationToJoinTreeIfNecessary(		final AssociationType type,		final String[] aliasedLhsColumns,		final String alias,		final List associations,		final Set visitedAssociations,		final String path,		int currentDepth,		final int joinType)	throws MappingException {				if (joinType<0) return;						// to avoid cartesian product problem, and since		// Loader cannot handle multiple collection roles		/*final boolean isCartesianProduct = joinType!=JoinFragment.INNER_JOIN && 			type.getAssociatedJoinable( getFactory() ).isCollection() &&			containsCollectionPersister(associations);		if ( !isCartesianProduct ) {*/					addAssociationToJoinTree(					type, 					aliasedLhsColumns, 					alias, 					associations, 					visitedAssociations, 					path,					currentDepth,					joinType			);					//}	}	/**	 * Add on association (one-to-one, many-to-one, or a collection) to a list 	 * of associations to be fetched by outerjoin 	 */	private void addAssociationToJoinTree(		final AssociationType type,		final String[] aliasedLhsColumns,		final String alias,		final List associations,		final Set visitedAssociations,		final String path,		final int currentDepth,		final int joinType)	throws MappingException {		Joinable joinable = type.getAssociatedJoinable( getFactory() );		String subalias = generateTableAlias(			associations.size()+1, //before adding to collection!			path, 			joinable		);		OuterJoinableAssociation assoc = new OuterJoinableAssociation(			type, 			alias, 			aliasedLhsColumns, 			subalias, 			joinType, 			getFactory(), 			enabledFilters		);		assoc.validateJoin(path);		associations.add(assoc);		int nextDepth = currentDepth+1;		if ( !joinable.isCollection() ) {			if (joinable instanceof OuterJoinLoadable) {				walkEntityTree(					(OuterJoinLoadable) joinable, 					subalias, 					associations, 					visitedAssociations, 					path, 					nextDepth				);			}		}		else {			if (joinable instanceof QueryableCollection) {				walkCollectionTree(					(QueryableCollection) joinable, 					subalias, 					associations, 					visitedAssociations, 					path, 					nextDepth				);			}		}	}	/**	 * Generate a select list of columns containing all properties of the entity classes	 */	protected final String selectString(List associations)	throws MappingException {		if ( associations.size()==0 ) {			return "";		}		else {			StringBuffer buf = new StringBuffer( associations.size() * 100 )				.append(", ");			String[] suffixes = getSuffixes();			String[] collectionSuffixes = getCollectionSuffixes();			int entityAliasCount=0;			int collectionAliasCount=0;			for ( int i=0; i<associations.size(); i++ ) {				OuterJoinableAssociation join = (OuterJoinableAssociation) associations.get(i);				OuterJoinableAssociation next = (i == associations.size() - 1)				        ? null				        : ( OuterJoinableAssociation ) associations.get( i + 1 );				final Joinable joinable = join.getJoinable();				final String entitySuffix = ( suffixes == null || entityAliasCount >= suffixes.length )				        ? null				        : suffixes[entityAliasCount];				final String collectionSuffix = ( collectionSuffixes == null || collectionAliasCount >= collectionSuffixes.length )				        ? null				        : collectionSuffixes[collectionAliasCount];				final String selectFragment = joinable.selectFragment(						next == null ? null : next.getJoinable(),						next == null ? null : next.getRHSAlias(),						join.getRHSAlias(),						entitySuffix,				        collectionSuffix,						join.getJoinType()==JoinFragment.LEFT_OUTER_JOIN				);				buf.append(selectFragment);				if ( joinable.consumesEntityAlias() ) entityAliasCount++;				if ( joinable.consumesCollectionAlias() && join.getJoinType()==JoinFragment.LEFT_OUTER_JOIN ) collectionAliasCount++;				if (					i<associations.size()-1 &&					selectFragment.trim().length()>0				) {					buf.append(", ");				}			}			return buf.toString();		}	}	protected String[] getSuffixes() {		return suffixes;	}	protected String[] getCollectionSuffixes() {		return collectionSuffixes;	}	protected String generateTableAlias(		final int n,		final String path,		final Joinable joinable	) {		return StringHelper.generateAlias( joinable.getName(), n );	}	protected String generateRootAlias(final String description) {		return StringHelper.generateAlias(description, 0);	}	/**	 * Generate a sequence of <tt>LEFT OUTER JOIN</tt> clauses for the given associations.	 */	protected final JoinFragment mergeOuterJoins(List associations)	throws MappingException {		JoinFragment outerjoin = getDialect().createOuterJoinFragment();		Iterator iter = associations.iterator();		OuterJoinableAssociation last = null;		while ( iter.hasNext() ) {			OuterJoinableAssociation oj = (OuterJoinableAssociation) iter.next();			if ( last != null && last.isManyToManyWith( oj ) ) {				oj.addManyToManyJoin( outerjoin, ( QueryableCollection ) last.getJoinable() );			}			else {				oj.addJoins(outerjoin);			}			last = oj;		}		last = null;		return outerjoin;	}	/**	 * Count the number of instances of Joinable which are actually	 * also instances of Loadable, or are one-to-many associations	 */	protected static final int countEntityPersisters(List associations)	throws MappingException {		int result = 0;		Iterator iter = associations.iterator();		while ( iter.hasNext() ) {			OuterJoinableAssociation oj = (OuterJoinableAssociation) iter.next();			if ( oj.getJoinable().consumesEntityAlias() ) {				result++;			}		}		return result;	}		/**	 * Count the number of instances of Joinable which are actually	 * also instances of PersistentCollection which are being fetched	 * by outer join	 */	protected static final int countCollectionPersisters(List associations)	throws MappingException {		int result = 0;		Iterator iter = associations.iterator();		while ( iter.hasNext() ) {			OuterJoinableAssociation oj = (OuterJoinableAssociation) iter.next();			if ( oj.getJoinType()==JoinFragment.LEFT_OUTER_JOIN && oj.getJoinable().isCollection() ) {				result++;			}		}		return result;	}		/**	 * Get the order by string required for collection fetching	 */	protected static final String orderBy(List associations)	throws MappingException {		StringBuffer buf = new StringBuffer();		Iterator iter = associations.iterator();		while ( iter.hasNext() ) {			OuterJoinableAssociation oj = (OuterJoinableAssociation) iter.next();			if ( oj.getJoinType()==JoinFragment.LEFT_OUTER_JOIN && oj.getJoinable().isCollection() ) {				final QueryableCollection queryableCollection = (QueryableCollection) oj.getJoinable();				if ( queryableCollection.hasOrdering() ) {					final String orderByString = queryableCollection.getSQLOrderByString( oj.getRHSAlias() );					buf.append( orderByString ).append(", ");				}			}		}		if ( buf.length()>0 ) buf.setLength( buf.length()-2 );		return buf.toString();	}		/**	 * Since Loader can handle only one collection role, we need	 * to ignore any collections after the first one	 */	/*protected static boolean containsCollectionPersister(List associations)	throws MappingException {		Iterator iter = associations.iterator();		while ( iter.hasNext() ) {			OuterJoinableAssociation oj = (OuterJoinableAssociation) iter.next();			if ( oj.getJoinable().isCollection() ) return true;		}		return false;	}*/	/**	 * Extend the path by the given property name	 */	private static String subPath(String path, String property) {		if ( path==null || path.length()==0) {			return property;		}		else {			return StringHelper.qualify(path, property);		}	}	/**	 * Render the where condition for a (batch) load by identifier / collection key	 */	protected StringBuffer whereString(String alias, String[] columnNames, int batchSize, String subquery) {		if ( columnNames.length==1 ) {			// if not a composite key, use "foo in (?, ?, ?)" for batching			// if no batch, and not a composite key, use "foo = ?"			InFragment in = new InFragment().setColumn( alias, columnNames[0] );			for ( int i=0; i<batchSize; i++ ) in.addValue("?");			return new StringBuffer( in.toFragmentString() );		}		else {			//a composite key			ConditionFragment byId = new ConditionFragment()				.setTableAlias(alias)				.setCondition( columnNames, "?" );				StringBuffer whereString = new StringBuffer();			if ( batchSize==1 ) {				// if no batch, use "foo = ? and bar = ?"				whereString.append( byId.toFragmentString() );			}			else {				// if a composite key, use "( (foo = ? and bar = ?) or (foo = ? and bar = ?) )" for batching				whereString.append('('); //TODO: unnecessary for databases with ANSI-style joins				DisjunctionFragment df = new DisjunctionFragment();				for ( int i=0; i<batchSize; i++ ) {					df.addCondition(byId);				}				whereString.append( df.toFragmentString() );				whereString.append(')'); //TODO: unnecessary for databases with ANSI-style joins			}			return whereString;		}	}	protected final String getSQLString() {		return sql;	}	protected final Loadable[] getEntityPersisters() {		return persisters;	}	protected int[] getOwners() {		return owners;	}	protected EntityType[] getOwnerAssociationTypes() {		return ownerAssociationType;	}	protected LockMode[] getLockModes(Map lockModes) {		return lockModeArray;	}		public Map getEnabledFilters() {		return enabledFilters;	}	protected void initPersisters(final List associations, final LockMode lockMode) throws MappingException {			final int joins = countEntityPersisters(associations);		final int collections = countCollectionPersisters(associations);		collectionOwners = collections==0 ? null : new int[collections];		collectionPersisters = collections==0 ? null : new CollectionPersister[collections];//		collectionSuffixes = collections==0 ? null : new String[collections];		collectionSuffixes = generateSuffixes( joins + 1, collections );		persisters = new Loadable[joins];		aliases = new String[joins];		owners = new int[joins];		ownerAssociationType = new EntityType[joins];		lockModeArray = ArrayHelper.fillArray(lockMode, joins);				int i=0;		int j=0;		Iterator iter = associations.iterator();		while ( iter.hasNext() ) {			final OuterJoinableAssociation oj = (OuterJoinableAssociation) iter.next();			if ( !oj.isCollection() ) {								persisters[i] = (Loadable) oj.getJoinable();				aliases[i] = oj.getRHSAlias();				owners[i] = oj.getOwner(associations);				ownerAssociationType[i] = (EntityType) oj.getJoinableType();				/*if ( oj.getJoinType()==JoinFragment.INNER_JOIN ) {					addAllToPropertySpaces( persisters[i].getQuerySpaces() );				}*/				i++;							}			else {								QueryableCollection collPersister = (QueryableCollection) oj.getJoinable();				if ( oj.getJoinType()==JoinFragment.LEFT_OUTER_JOIN ) {					//it must be a collection fetch					collectionPersisters[j] = collPersister;					collectionOwners[j] = oj.getOwner(associations);//					collectionSuffixes[j] = Integer.toString( j ) + "_";					j++;				}				/*else {					addAllToPropertySpaces( collPersister.getCollectionSpaces() );				}*/					if ( collPersister.isOneToMany() ) {					persisters[i] = (Loadable) collPersister.getElementPersister();					aliases[i] = oj.getRHSAlias();					i++;				}			}		}			if ( ArrayHelper.isAllNegative(owners) ) owners = null;		if ( collectionOwners!=null && ArrayHelper.isAllNegative(collectionOwners) ) {			collectionOwners = null;		}	}	protected final String[] getAliases() {		return aliases;	}	protected final CollectionPersister[] getCollectionPersisters() {		return collectionPersisters;	}	protected final int[] getCollectionOwners() {		return collectionOwners;	}	protected String orderBy(final List associations, final String orderBy) {		String fullOrderBy = orderBy(associations);		if ( fullOrderBy.length()== 0 ) {			fullOrderBy = orderBy;		}		else if ( orderBy.length()!=0 ) {			fullOrderBy = fullOrderBy + ", " + orderBy;		}		return fullOrderBy;	}	/*protected final void addAllToPropertySpaces(Serializable[] spaces) {		for ( int i=0; i<spaces.length; i++ ) {			addToPropertySpaces( spaces[i] );		}	}		protected void addToPropertySpaces(Serializable space) {		throw new AssertionFailure("only criteria queries need to autoflush");	}*/}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?