⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 joinwalker.java

📁 hibernate-3.1.3-all-src.zip 面向对象的访问数据库工具
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
//$Id: JoinWalker.java 7652 2005-07-26 05:51:47Z oneovthafew $
package org.hibernate.loader;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hibernate.FetchMode;
import org.hibernate.LockMode;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.CascadeStyle;
import org.hibernate.engine.JoinHelper;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.sql.ConditionFragment;
import org.hibernate.sql.DisjunctionFragment;
import org.hibernate.sql.InFragment;
import org.hibernate.sql.JoinFragment;
import org.hibernate.type.AbstractComponentType;
import org.hibernate.type.AssociationType;
import org.hibernate.type.EntityType;
import org.hibernate.type.ForeignKeyDirection;
import org.hibernate.type.Type;
import org.hibernate.util.ArrayHelper;
import org.hibernate.util.StringHelper;

/**
 * Walks the metamodel, searching for joins, and collecting
 * together information needed by <tt>OuterJoinLoader</tt>.
 * 
 * @see OuterJoinLoader
 * @author Gavin King, Jon Lipsky
 */
public class JoinWalker {
	
	private final SessionFactoryImplementor factory;
	protected final List associations = new ArrayList();
	private final Set visitedAssociationKeys = new HashSet();
	private final Map enabledFilters;

	protected String[] suffixes;
	protected String[] collectionSuffixes;
	protected Loadable[] persisters;
	protected int[] owners;
	protected EntityType[] ownerAssociationTypes;
	protected CollectionPersister[] collectionPersisters;
	protected int[] collectionOwners;
	protected String[] aliases;
	protected LockMode[] lockModeArray;
	protected String sql;
	
	public String[] getCollectionSuffixes() {
		return collectionSuffixes;
	}

	public void setCollectionSuffixes(String[] collectionSuffixes) {
		this.collectionSuffixes = collectionSuffixes;
	}

	public LockMode[] getLockModeArray() {
		return lockModeArray;
	}

	public void setLockModeArray(LockMode[] lockModeArray) {
		this.lockModeArray = lockModeArray;
	}

	public String[] getSuffixes() {
		return suffixes;
	}

	public void setSuffixes(String[] suffixes) {
		this.suffixes = suffixes;
	}

	public String[] getAliases() {
		return aliases;
	}

	public void setAliases(String[] aliases) {
		this.aliases = aliases;
	}

	public int[] getCollectionOwners() {
		return collectionOwners;
	}

	public void setCollectionOwners(int[] collectionOwners) {
		this.collectionOwners = collectionOwners;
	}

	public CollectionPersister[] getCollectionPersisters() {
		return collectionPersisters;
	}

	public void setCollectionPersisters(CollectionPersister[] collectionPersisters) {
		this.collectionPersisters = collectionPersisters;
	}

	public EntityType[] getOwnerAssociationTypes() {
		return ownerAssociationTypes;
	}

	public void setOwnerAssociationTypes(EntityType[] ownerAssociationType) {
		this.ownerAssociationTypes = ownerAssociationType;
	}

	public int[] getOwners() {
		return owners;
	}

	public void setOwners(int[] owners) {
		this.owners = owners;
	}

	public Loadable[] getPersisters() {
		return persisters;
	}

	public void setPersisters(Loadable[] persisters) {
		this.persisters = persisters;
	}

	public String getSQLString() {
		return sql;
	}

	public void setSql(String sql) {
		this.sql = sql;
	}

	protected SessionFactoryImplementor getFactory() {
		return factory;
	}

	protected Dialect getDialect() {
		return factory.getDialect();
	}
	
	protected Map getEnabledFilters() {
		return enabledFilters;
	}

	protected JoinWalker(SessionFactoryImplementor factory, Map enabledFilters) {
		this.factory = factory;
		this.enabledFilters = enabledFilters;
	}

	/**
	 * 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 String path,
		int currentDepth,
		final int joinType)
	throws MappingException {
		
		if (joinType>=0) {	
			addAssociationToJoinTree(
					type, 
					aliasedLhsColumns, 
					alias, 
					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 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,
					path, 
					nextDepth
				);
			}
		}
		else {
			if (joinable instanceof QueryableCollection) {
				walkCollectionTree(
					(QueryableCollection) joinable, 
					subalias, 
					path, 
					nextDepth
				);
			}
		}

	}

	/**
	 * For an entity class, return a list of associations to be fetched by outerjoin
	 */
	protected final void walkEntityTree(OuterJoinLoadable persister, String alias)
	throws MappingException {
		walkEntityTree(persister, alias, "", 0);
	}

	/**
	 * For a collection role, return a list of associations to be fetched by outerjoin
	 */
	protected final void walkCollectionTree(QueryableCollection persister, String alias)
	throws MappingException {
		walkCollectionTree(persister, alias, "", 0);
		//TODO: when this is the entry point, we should use an INNER_JOIN for fetching the many-to-many elements!
	}

	/**
	 * For a collection role, return a list of associations to be fetched by outerjoin
	 */
	private void walkCollectionTree(
		final QueryableCollection persister,
		final String alias,
		final String path,
		final int currentDepth)
	throws MappingException {

		if ( persister.isOneToMany() ) {
			walkEntityTree(
					(OuterJoinLoadable) persister.getElementPersister(),
					alias,
					path,
					currentDepth
				);
		}
		else {
			Type type = persister.getElementType();
			if ( type.isAssociationType() ) {
				// a many-to-many;
				// decrement currentDepth here to allow join across the association table
				// without exceeding MAX_FETCH_DEPTH (i.e. the "currentDepth - 1" bit)
				AssociationType associationType = (AssociationType) type;
				String[] aliasedLhsColumns = persister.getElementColumnNames(alias);
				String[] lhsColumns = persister.getElementColumnNames();
				// if the current depth is 0, the root thing being loaded is the
				// many-to-many collection itself.  Here, it is alright to use
				// an inner join...
				boolean useInnerJoin = currentDepth == 0;
				final int joinType = getJoinType(
						associationType,
						persister.getFetchMode(),
						path,
						persister.getTableName(),
						lhsColumns,
						!useInnerJoin,
						currentDepth - 1, 
						null //operations which cascade as far as the collection also cascade to collection elements
					);
				addAssociationToJoinTreeIfNecessary(
						associationType,
						aliasedLhsColumns,
						alias,
						path,
						currentDepth - 1,
						joinType
					);
			}
			else if ( type.isComponentType() ) {
				walkCompositeElementTree(
						(AbstractComponentType) type,
						persister.getElementColumnNames(),
						persister,
						alias,
						path,
						currentDepth
					);
			}
		}

	}
	
	/**
	 * Walk the tree for a particular entity association
	 */
	private final void walkEntityAssociationTree(
		final AssociationType associationType,
		final OuterJoinLoadable persister,
		final int propertyNumber,
		final String alias,
		final String path,
		final boolean nullable,
		final int currentDepth)
	throws MappingException {

		String[] aliasedLhsColumns = JoinHelper.getAliasedLHSColumnNames(
				associationType, alias, propertyNumber, persister, getFactory()
			);

		String[] lhsColumns = JoinHelper.getLHSColumnNames(
				associationType, propertyNumber, persister, getFactory()
			);
		String lhsTable = JoinHelper.getLHSTableName(associationType, propertyNumber, persister);

		String subpath = subPath( path, persister.getSubclassPropertyName(propertyNumber) );
		int joinType = getJoinType(
				associationType,
				persister.getFetchMode(propertyNumber),
				subpath,
				lhsTable,
				lhsColumns,
				nullable,
				currentDepth, 
				persister.getCascadeStyle(propertyNumber)
			);
		addAssociationToJoinTreeIfNecessary(
				associationType,
				aliasedLhsColumns,
				alias,
				subpath,
				currentDepth,
				joinType
			);

	}

	/**
	 * For an entity class, add to a list of associations to be fetched 
	 * by outerjoin
	 */
	private final void walkEntityTree(
		final OuterJoinLoadable persister,
		final String alias,
		final String path,
		final int currentDepth) 
	throws MappingException {

		int n = persister.countSubclassProperties();
		for ( int i=0; i<n; i++ ) {
			Type type = persister.getSubclassPropertyType(i);
			if ( type.isAssociationType() ) {
				walkEntityAssociationTree(
					(AssociationType) type,
					persister,
					i,
					alias,
					path,
					persister.isSubclassPropertyNullable(i),
					currentDepth
				);
			}
			else if ( type.isComponentType() ) {
				walkComponentTree(
					(AbstractComponentType) type,
					i,
					0,
					persister,
					alias,
					subPath( path, persister.getSubclassPropertyName(i) ),
					currentDepth
				);
			}
		}
	}

	/**
	 * For a component, add to a list of associations to be fetched by outerjoin
	 */
	private void walkComponentTree(
		final AbstractComponentType componentType,
		final int propertyNumber,
		int begin,
		final OuterJoinLoadable persister,
		final String alias,
		final String path,
		final int currentDepth
	) throws MappingException {

		Type[] types = componentType.getSubtypes();
		String[] propertyNames = componentType.getPropertyNames();
		for ( int i=0; i <types.length; i++ ) {

			if ( types[i].isAssociationType() ) {
				AssociationType associationType = (AssociationType) types[i];

				String[] aliasedLhsColumns = JoinHelper.getAliasedLHSColumnNames(
					associationType, alias, propertyNumber, begin, persister, getFactory()
				);

				String[] lhsColumns = JoinHelper.getLHSColumnNames(
					associationType, propertyNumber, begin, persister, getFactory()
				);
				String lhsTable = JoinHelper.getLHSTableName(associationType, propertyNumber, persister);

				String subpath = subPath( path, propertyNames[i] );
				final boolean[] propertyNullability = componentType.getPropertyNullability();
				final int joinType = getJoinType(
						associationType,
						componentType.getFetchMode(i),
						subpath,
						lhsTable,
						lhsColumns,
						propertyNullability==null || propertyNullability[i],
						currentDepth, 
						componentType.getCascadeStyle(i)
					);
				addAssociationToJoinTreeIfNecessary(			
						associationType,
						aliasedLhsColumns,
						alias,
						subpath,
						currentDepth,
						joinType
					);

			}
			else if ( types[i].isComponentType() ) {
				String subpath = subPath( path, propertyNames[i] );
				walkComponentTree(
						(AbstractComponentType) types[i],
						propertyNumber,
						begin,
						persister,
						alias,
						subpath,
						currentDepth
					);
			}
			
			begin+=types[i].getColumnSpan( getFactory() );
		}

	}

⌨️ 快捷键说明

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