📄 outerjoinloader.java
字号:
Type[] types = compositeType.getSubtypes(); String[] propertyNames = compositeType.getPropertyNames(); int begin = 0; for ( int i=0; i <types.length; i++ ) { int length = types[i].getColumnSpan(factory); String[] range = ArrayHelper.slice(cols, begin, length); if ( types[i].isAssociationType() ) { AssociationType associationType = (AssociationType) types[i]; //simple, because we can't have a one-to-one or a collection in a composite-element: String[] aliasedForeignKeyColumns = StringHelper.qualify(alias, range); String subpath = subPath( path, propertyNames[i] ); int joinType = getJoinType( associationType, compositeType.enableJoinedFetch(i), subpath, persister.getTableName(), range, factory ); if (joinType>=0) { walkAssociationTree( associationType, aliasedForeignKeyColumns, persister, alias, associations, visitedPersisters, subpath, currentDepth, joinType, factory ); } } else if ( types[i].isComponentType() ) { String subpath = subPath( path, propertyNames[i] ); walkCompositeElementTree( (AbstractComponentType) types[i], range, persister, alias, associations, visitedPersisters, subpath, currentDepth, factory ); } begin+=length; } } /** * Does the mapping, and Hibernate default semantics, specify that * this association should be fetched by outer joining */ protected boolean isJoinedFetchEnabledByDefault(int config, AssociationType type, SessionFactoryImplementor factory) throws MappingException { if ( !type.isEntityType() && !type.isPersistentCollectionType() ) { return false; } else { if (config==EAGER) return true; if (config==LAZY) return false; if ( !factory.isOuterJoinedFetchEnabled() ) return false; if ( type.isEntityType() ) { EntityType entityType =(EntityType) type; ClassPersister persister = factory.getPersister( entityType.getAssociatedClass() ); return !persister.hasProxy() || ( entityType.isOneToOne() && ( (OneToOneType) entityType ).isNullable() ); } 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 walkAssociationTree( AssociationType type, String[] aliasedForeignKeyColumns, Joinable persister, String alias, List associations, Set visitedPersisters, String path, int currentDepth, int joinType, SessionFactoryImplementor factory) throws MappingException { Joinable joinable = type.getJoinable(factory); Integer maxFetchDepth = factory.getMaximumFetchDepth(); //int currentDepth = associations.size(); boolean enable = (joinType==JoinFragment.INNER_JOIN) || ( // ALWAYS continue in the case of an inner join (indicates "not just a performance opt") ( maxFetchDepth==null || currentDepth < maxFetchDepth.intValue() ) && // not too deep !visitedPersisters.contains(joinable) && // to avoid circularities ( !joinable.isCollection() || !containsCollectionPersister(associations) ) // to avoid cartesian product problem ); if (enable) { visitedPersisters.add(persister); OuterJoinableAssociation assoc = new OuterJoinableAssociation(); associations.add(assoc); String subalias = generateTableAlias( joinable.getName(), associations.size(), path, joinable.isManyToMany() ); //after adding to collection! assoc.joinable = joinable; assoc.tableName = joinable.getTableName(); assoc.primaryKeyColumns = type.getReferencedColumns(factory); assoc.foreignKeyColumns = aliasedForeignKeyColumns; assoc.subalias = subalias; assoc.owner = getPosition(alias, associations); assoc.isOneToOne = type.isEntityType() && ( (EntityType) type ).isOneToOne(); assoc.joinType = joinType; if ( assoc.foreignKeyColumns.length!=assoc.primaryKeyColumns.length || assoc.foreignKeyColumns.length==0 ) { throw new MappingException("invalid join columns for association: " + path); } int nextDepth = currentDepth+1; if ( !joinable.isCollection() ) { walkClassTree( (Loadable) joinable, subalias, associations, visitedPersisters, path, nextDepth, factory ); } else { walkCollectionTree( (QueryableCollection) joinable, subalias, associations, visitedPersisters, path, nextDepth, factory ); } } } protected final String getSQLString() { return sql; } protected final Loadable[] getPersisters() { return classPersisters; } /** * Generate a select list of columns containing all properties of the entity classes */ protected final String selectString(List associations, SessionFactoryImplementor factory) throws MappingException { if ( associations.size()==0 ) { return StringHelper.EMPTY_STRING; } else { StringBuffer buf = new StringBuffer( associations.size() * 100 ) .append(StringHelper.COMMA_SPACE); int aliasCount=0; for ( int i=0; i<associations.size(); i++ ) { OuterJoinableAssociation join = (OuterJoinableAssociation) associations.get(i); buf.append( join.joinable.joinSelectFragment( join.subalias, getSuffixes()[aliasCount] ) ); if ( join.joinable.consumesAlias() ) aliasCount++; if ( i<associations.size()-1 ) buf.append(StringHelper.COMMA_SPACE); } return buf.toString(); } } protected String[] getSuffixes() { return suffixes; } protected String generateTableAlias(String tableName, int n, String path, boolean isLinkTable) { return generateTableAlias(tableName, n); } /** * Generate a nice alias for the given table name and unique * integer. * @return an alias of the form <tt>foo1_</tt> */ private static String generateTableAlias(String tableName, int n) { tableName = StringHelper.unqualify(tableName); //TODO: this is broken if we have quoted identifier with a "." return new Alias( 10, Integer.toString(n) + StringHelper.UNDERSCORE ) .toAliasString( tableName.toLowerCase() ); } protected String generateRootAlias(String tableName) { return generateTableAlias(tableName, 0); } protected CollectionPersister getCollectionPersister() { return null; } /** * Generate a sequence of <tt>LEFT OUTER JOIN</tt> clauses for the given associations. */ protected final JoinFragment mergeOuterJoins(List associations) { JoinFragment outerjoin = dialect.createOuterJoinFragment(); Iterator iter = associations.iterator(); while ( iter.hasNext() ) { OuterJoinLoader.OuterJoinableAssociation oj = (OuterJoinLoader.OuterJoinableAssociation) iter.next(); outerjoin.addJoin( oj.tableName, oj.subalias, oj.foreignKeyColumns, oj.primaryKeyColumns, oj.joinType ); outerjoin.addJoins( oj.joinable.fromJoinFragment(oj.subalias, false, true), oj.joinable.whereJoinFragment(oj.subalias, false, true) ); } 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 countClassPersisters(List associations) { int result = 0; Iterator iter = associations.iterator(); while ( iter.hasNext() ) { OuterJoinLoader.OuterJoinableAssociation oj = (OuterJoinLoader.OuterJoinableAssociation) iter.next(); if ( oj.joinable.consumesAlias() ) result++; } return result; } protected static boolean containsCollectionPersister(List associations) { Iterator iter = associations.iterator(); while ( iter.hasNext() ) { OuterJoinLoader.OuterJoinableAssociation oj = (OuterJoinLoader.OuterJoinableAssociation) iter.next(); if ( oj.joinable.isCollection() ) return true; } return false; } protected LockMode[] getLockModes(Map lockModes) { return lockModeArray; } protected LockMode[] createLockModeArray(int length, LockMode lockMode) { LockMode[] array = new LockMode[length]; Arrays.fill(array, lockMode); return array; } 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 static StringBuffer whereString(String alias, String[] columnNames, int batchSize) { ConditionFragment byId = new ConditionFragment() .setTableAlias(alias) .setCondition( columnNames, "?" ); StringBuffer whereString = new StringBuffer(); if (batchSize==1) { whereString.append( byId.toFragmentString() ); } else { whereString.append(StringHelper.OPEN_PAREN); //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(StringHelper.CLOSE_PAREN); //TODO: unnecessary for databases with ANSI-style joins } return whereString; } /** * Get the position of the join with the given alias in the * list of joins, or -1 if not found */ private static int getPosition(String alias, List associations) { for ( int i=0; i<associations.size(); i++ ) { OuterJoinableAssociation oj = (OuterJoinableAssociation) associations.get(i); if ( oj.subalias.equals(alias) ) return i; } return -1; } private static String[] getAliasedForeignKeyColumns(Loadable persister, String alias, AssociationType associationType, String[] aliasedPropertyColumns) { if ( associationType.usePrimaryKeyAsForeignKey() ) { // a one-to-one association, or collection return StringHelper.qualify( alias, persister.getIdentifierColumnNames() ); } else { // a many-to-one association return aliasedPropertyColumns; } } private static String[] getForeignKeyColumns(Loadable persister, AssociationType associationType, String[] propertyColumns) { if ( associationType.usePrimaryKeyAsForeignKey() ) { return persister.getIdentifierColumnNames(); } else { return propertyColumns; } } protected int[] getOwners() { return owners; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -