📄 outerjoinloader.java
字号:
final boolean[] propertyNullability = componentType.getPropertyNullability(); final int joinType = getJoinType( associationType, componentType.getFetchMode(i), subpath, visitedAssociations, lhsTable, 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] ); walkComponentTree( (AbstractComponentType) types[i], propertyNumber, begin, persister, alias, associations, visitedAssociations, subpath, currentDepth ); } begin+=types[i].getColumnSpan( getFactory() ); } } /** * For a composite element, add to a list of associations to be fetched by outerjoin */ private void walkCompositeElementTree( final AbstractComponentType compositeType, final String[] cols, final QueryableCollection persister, final String alias, final List associations, final Set visitedAssociations, final String path, final int currentDepth) throws MappingException { Type[] types = compositeType.getSubtypes(); String[] propertyNames = compositeType.getPropertyNames(); int begin = 0; for ( int i=0; i <types.length; i++ ) { int length = types[i].getColumnSpan( getFactory() ); String[] lhsColumns = 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 // (or even a property-ref) in a composite-element: String[] aliasedLhsColumns = StringHelper.qualify(alias, lhsColumns); String subpath = subPath( path, propertyNames[i] ); final boolean[] propertyNullability = compositeType.getPropertyNullability(); final int joinType = getJoinType( associationType, compositeType.getFetchMode(i), subpath, 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(", "); int aliasCount=0; for ( int i=0; i<associations.size(); i++ ) { OuterJoinableAssociation join = (OuterJoinableAssociation) associations.get(i); final Joinable joinable = join.getJoinable(); final String selectFragment = joinable.selectFragment( join.getRHSAlias(), getSuffixes()[aliasCount], join.getJoinType()==JoinFragment.LEFT_OUTER_JOIN ); buf.append(selectFragment); if ( joinable.consumesAlias() ) aliasCount++; if ( i<associations.size()-1 && selectFragment.trim().length()>0 ) { buf.append(", "); } } return buf.toString(); } } protected String[] getSuffixes() { return suffixes; } 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(); while ( iter.hasNext() ) { OuterJoinableAssociation oj = (OuterJoinableAssociation) iter.next(); oj.addJoins(outerjoin); } 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().consumesAlias() ) result++; } return result; } /** * 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 AssociationType[] getOwnerAssociationTypes() { return ownerAssociationType; } protected LockMode[] getLockModes(Map lockModes) { return lockModeArray; } public Map getEnabledFilters() { return enabledFilters; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -