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 + -
显示快捷键?