1 package org.hibernate.engine; 3 4 import java.util.ArrayList ; 5 import java.util.List ; 6 import java.util.Map ; 7 8 import org.hibernate.MappingException; 9 import org.hibernate.persister.entity.Joinable; 10 import org.hibernate.persister.collection.QueryableCollection; 11 import org.hibernate.sql.JoinFragment; 12 import org.hibernate.sql.QueryJoinFragment; 13 import org.hibernate.type.AssociationType; 14 import org.hibernate.util.CollectionHelper; 15 16 19 public class JoinSequence { 20 21 private final SessionFactoryImplementor factory; 22 private final List joins = new ArrayList (); 23 private boolean useThetaStyle = false; 24 private final StringBuffer conditions = new StringBuffer (); 25 private String rootAlias; 26 private Joinable rootJoinable; 27 private Selector selector; 28 private JoinSequence next; 29 private boolean isFromPart = false; 30 31 public String toString() { 32 StringBuffer buf = new StringBuffer (); 33 buf.append( "JoinSequence{" ); 34 if ( rootJoinable != null ) { 35 buf.append( rootJoinable ) 36 .append( '[' ) 37 .append( rootAlias ) 38 .append( ']' ); 39 } 40 for ( int i = 0; i < joins.size(); i++ ) { 41 buf.append( "->" ).append( joins.get( i ) ); 42 } 43 return buf.append( '}' ).toString(); 44 } 45 46 final class Join { 47 48 private final AssociationType associationType; 49 private final Joinable joinable; 50 private final int joinType; 51 private final String alias; 52 private final String [] lhsColumns; 53 54 Join(AssociationType associationType, String alias, int joinType, String [] lhsColumns) 55 throws MappingException { 56 this.associationType = associationType; 57 this.joinable = associationType.getAssociatedJoinable( factory ); 58 this.alias = alias; 59 this.joinType = joinType; 60 this.lhsColumns = lhsColumns; 61 } 62 63 String getAlias() { 64 return alias; 65 } 66 67 AssociationType getAssociationType() { 68 return associationType; 69 } 70 71 Joinable getJoinable() { 72 return joinable; 73 } 74 75 int getJoinType() { 76 return joinType; 77 } 78 79 String [] getLHSColumns() { 80 return lhsColumns; 81 } 82 83 public String toString() { 84 return joinable.toString() + '[' + alias + ']'; 85 } 86 } 87 88 public JoinSequence(SessionFactoryImplementor factory) { 89 this.factory = factory; 90 } 91 92 public JoinSequence getFromPart() { 93 JoinSequence fromPart = new JoinSequence( factory ); 94 fromPart.joins.addAll( this.joins ); 95 fromPart.useThetaStyle = this.useThetaStyle; 96 fromPart.rootAlias = this.rootAlias; 97 fromPart.rootJoinable = this.rootJoinable; 98 fromPart.selector = this.selector; 99 fromPart.next = this.next == null ? null : this.next.getFromPart(); 100 fromPart.isFromPart = true; 101 return fromPart; 102 } 103 104 public JoinSequence copy() { 105 JoinSequence copy = new JoinSequence( factory ); 106 copy.joins.addAll( this.joins ); 107 copy.useThetaStyle = this.useThetaStyle; 108 copy.rootAlias = this.rootAlias; 109 copy.rootJoinable = this.rootJoinable; 110 copy.selector = this.selector; 111 copy.next = this.next == null ? null : this.next.copy(); 112 copy.isFromPart = this.isFromPart; 113 copy.conditions.append( this.conditions.toString() ); 114 return copy; 115 } 116 117 public JoinSequence addJoin(AssociationType associationType, String alias, int joinType, String [] referencingKey) 118 throws MappingException { 119 joins.add( new Join( associationType, alias, joinType, referencingKey ) ); 120 return this; 121 } 122 123 public JoinFragment toJoinFragment() throws MappingException { 124 return toJoinFragment( CollectionHelper.EMPTY_MAP, true ); 125 } 126 127 public JoinFragment toJoinFragment(Map enabledFilters, boolean includeExtraJoins) throws MappingException { 128 return toJoinFragment( enabledFilters, includeExtraJoins, null ); 129 } 130 131 public JoinFragment toJoinFragment(Map enabledFilters, boolean includeExtraJoins, String extraOnClause) throws MappingException { 132 QueryJoinFragment joinFragment = new QueryJoinFragment( factory.getDialect(), useThetaStyle ); 133 if ( rootJoinable != null ) { 134 joinFragment.addCrossJoin( rootJoinable.getTableName(), rootAlias ); 135 String filterCondition = rootJoinable.filterFragment( rootAlias, enabledFilters ); 136 joinFragment.setHasFilterCondition( joinFragment.addCondition( filterCondition ) ); 140 if (includeExtraJoins) { addExtraJoins( joinFragment, rootAlias, rootJoinable, true ); 142 } 143 } 144 145 Joinable last = rootJoinable; 146 147 for ( int i = 0; i < joins.size(); i++ ) { 148 Join join = ( Join ) joins.get( i ); 149 String on = join.getAssociationType().getOnCondition( join.getAlias(), factory, enabledFilters ); 150 String condition = null; 151 if ( last != null && 152 isManyToManyRoot( last ) && 153 ( ( QueryableCollection ) last ).getElementType() == join.getAssociationType() ) { 154 String manyToManyFilter = ( ( QueryableCollection ) last ) 158 .getManyToManyFilterFragment( join.getAlias(), enabledFilters ); 159 condition = "".equals( manyToManyFilter ) 160 ? on 161 : "".equals( on ) 162 ? manyToManyFilter 163 : on + " and " + manyToManyFilter; 164 } 165 else { 166 condition = on; 167 } 168 if ( extraOnClause != null ) { 169 condition += " and " + extraOnClause; 170 } 171 joinFragment.addJoin( 172 join.getJoinable().getTableName(), 173 join.getAlias(), 174 join.getLHSColumns(), 175 JoinHelper.getRHSColumnNames( join.getAssociationType(), factory ), 176 join.joinType, 177 condition 178 ); 179 if (includeExtraJoins) { addExtraJoins( joinFragment, join.getAlias(), join.getJoinable(), join.joinType == JoinFragment.INNER_JOIN ); 181 } 182 last = join.getJoinable(); 183 } 184 if ( next != null ) { 185 joinFragment.addFragment( next.toJoinFragment( enabledFilters, includeExtraJoins ) ); 186 } 187 joinFragment.addCondition( conditions.toString() ); 188 if ( isFromPart ) joinFragment.clearWherePart(); 189 return joinFragment; 190 } 191 192 private boolean isManyToManyRoot(Joinable joinable) { 193 if ( joinable != null && joinable.isCollection() ) { 194 QueryableCollection persister = ( QueryableCollection ) joinable; 195 return persister.isManyToMany(); 196 } 197 return false; 198 } 199 200 private boolean isIncluded(String alias) { 201 return selector != null && selector.includeSubclasses( alias ); 202 } 203 204 private void addExtraJoins(JoinFragment joinFragment, String alias, Joinable joinable, boolean innerJoin) { 205 boolean include = isIncluded( alias ); 206 joinFragment.addJoins( joinable.fromJoinFragment( alias, innerJoin, include ), 207 joinable.whereJoinFragment( alias, innerJoin, include ) ); 208 } 209 210 public JoinSequence addCondition(String condition) { 211 if ( condition.trim().length() != 0 ) { 212 if ( !condition.startsWith( " and " ) ) conditions.append( " and " ); 213 conditions.append( condition ); 214 } 215 return this; 216 } 217 218 public JoinSequence addCondition(String alias, String [] columns, String condition) { 219 for ( int i = 0; i < columns.length; i++ ) { 220 conditions.append( " and " ) 221 .append( alias ) 222 .append( '.' ) 223 .append( columns[i] ) 224 .append( condition ); 225 } 226 return this; 227 } 228 229 public JoinSequence setRoot(Joinable joinable, String alias) { 230 this.rootAlias = alias; 231 this.rootJoinable = joinable; 232 return this; 233 } 234 235 public JoinSequence setNext(JoinSequence next) { 236 this.next = next; 237 return this; 238 } 239 240 public JoinSequence setSelector(Selector s) { 241 this.selector = s; 242 return this; 243 } 244 245 public JoinSequence setUseThetaStyle(boolean useThetaStyle) { 246 this.useThetaStyle = useThetaStyle; 247 return this; 248 } 249 250 public boolean isThetaStyle() { 251 return useThetaStyle; 252 } 253 254 public int getJoinCount() { 255 return joins.size(); 256 } 257 258 public static interface Selector { 259 public boolean includeSubclasses(String alias); 260 } 261 } 262 | Popular Tags |