KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > persister > entity > SingleTableEntityPersister


1 //$Id: SingleTableEntityPersister.java,v 1.11 2005/07/21 01:11:52 oneovthafew Exp $
2
package org.hibernate.persister.entity;
3
4 import java.io.Serializable JavaDoc;
5 import java.util.ArrayList JavaDoc;
6 import java.util.HashMap JavaDoc;
7 import java.util.HashSet JavaDoc;
8 import java.util.Iterator JavaDoc;
9 import java.util.Map JavaDoc;
10
11 import org.hibernate.EntityMode;
12 import org.hibernate.HibernateException;
13 import org.hibernate.MappingException;
14 import org.hibernate.cache.CacheConcurrencyStrategy;
15 import org.hibernate.engine.Mapping;
16 import org.hibernate.engine.SessionFactoryImplementor;
17 import org.hibernate.mapping.Column;
18 import org.hibernate.mapping.Formula;
19 import org.hibernate.mapping.Join;
20 import org.hibernate.mapping.PersistentClass;
21 import org.hibernate.mapping.Property;
22 import org.hibernate.mapping.Selectable;
23 import org.hibernate.mapping.Subclass;
24 import org.hibernate.mapping.Table;
25 import org.hibernate.mapping.Value;
26 import org.hibernate.sql.InFragment;
27 import org.hibernate.sql.Insert;
28 import org.hibernate.sql.SelectFragment;
29 import org.hibernate.type.AssociationType;
30 import org.hibernate.type.DiscriminatorType;
31 import org.hibernate.type.Type;
32 import org.hibernate.util.ArrayHelper;
33 import org.hibernate.util.MarkerObject;
34
35 /**
36  * The default implementation of the <tt>EntityPersister</tt> interface.
37  * Implements the "table-per-class-hierarchy" or "roll-up" mapping strategy
38  * for an entity class and its inheritence hierarchy. This is implemented
39  * as a single table holding all classes in the hierarchy with a discrimator
40  * column used to determine which concrete class is referenced.
41  *
42  * @author Gavin King
43  */

44 public class SingleTableEntityPersister extends BasicEntityPersister {
45
46     // the class hierarchy structure
47
private final int joinSpan;
48     private final String JavaDoc[] qualifiedTableNames;
49     private final boolean[] isInverseTable;
50     private final boolean[] isNullableTable;
51     private final String JavaDoc[][] keyColumnNames;
52     private final boolean[] cascadeDeleteEnabled;
53     private final boolean hasSequentialSelects;
54     
55     private final String JavaDoc[] spaces;
56
57     private final String JavaDoc[] subclassClosure;
58
59     private final String JavaDoc[] subclassTableNameClosure;
60     private final boolean[] subclassTableIsLazyClosure;
61     private final boolean[] isInverseSubclassTable;
62     private final boolean[] isNullableSubclassTable;
63     private final boolean[] subclassTableSequentialSelect;
64     private final String JavaDoc[][] subclassTableKeyColumnClosure;
65     private final boolean[] isClassOrSuperclassTable;
66
67     // properties of this class, including inherited properties
68
private final int[] propertyTableNumbers;
69
70     // the closure of all columns used by the entire hierarchy including
71
// subclasses and superclasses of this class
72
private final int[] subclassPropertyTableNumberClosure;
73
74     private final int[] subclassColumnTableNumberClosure;
75     private final int[] subclassFormulaTableNumberClosure;
76
77     // discriminator column
78
private final Map JavaDoc subclassesByDiscriminatorValue = new HashMap JavaDoc();
79     private final boolean forceDiscriminator;
80     private final String JavaDoc discriminatorColumnName;
81     private final String JavaDoc discriminatorFormula;
82     private final String JavaDoc discriminatorFormulaTemplate;
83     private final String JavaDoc discriminatorAlias;
84     private final Type discriminatorType;
85     private final String JavaDoc discriminatorSQLValue;
86     private final boolean discriminatorInsertable;
87
88     private final String JavaDoc[] constraintOrderedTableNames;
89     private final String JavaDoc[][] constraintOrderedKeyColumnNames;
90
91     //private final Map propertyTableNumbersByName = new HashMap();
92
private final Map JavaDoc propertyTableNumbersByNameAndSubclass = new HashMap JavaDoc();
93     
94     private final Map JavaDoc sequentialSelectStringsByEntityName = new HashMap JavaDoc();
95
96     private static final Object JavaDoc NULL_DISCRIMINATOR = new MarkerObject("<null discriminator>");
97     private static final Object JavaDoc NOT_NULL_DISCRIMINATOR = new MarkerObject("<not null discriminator>");
98
99     //INITIALIZATION:
100

101     public SingleTableEntityPersister(
102             final PersistentClass persistentClass,
103             final CacheConcurrencyStrategy cache,
104             final SessionFactoryImplementor factory,
105             final Mapping mapping)
106     throws HibernateException {
107
108         super(persistentClass, cache, factory);
109
110         // CLASS + TABLE
111

112         joinSpan = persistentClass.getJoinClosureSpan()+1;
113         qualifiedTableNames = new String JavaDoc[joinSpan];
114         isInverseTable = new boolean[joinSpan];
115         isNullableTable = new boolean[joinSpan];
116         keyColumnNames = new String JavaDoc[joinSpan][];
117         final Table table = persistentClass.getRootTable();
118         qualifiedTableNames[0] = table.getQualifiedName(
119                 factory.getDialect(),
120                 factory.getSettings().getDefaultCatalogName(),
121                 factory.getSettings().getDefaultSchemaName()
122         );
123         isInverseTable[0] = false;
124         isNullableTable[0] = false;
125         keyColumnNames[0] = getIdentifierColumnNames();
126         cascadeDeleteEnabled = new boolean[joinSpan];
127
128         // Custom sql
129
customSQLInsert = new String JavaDoc[joinSpan];
130         customSQLUpdate = new String JavaDoc[joinSpan];
131         customSQLDelete = new String JavaDoc[joinSpan];
132         insertCallable = new boolean[joinSpan];
133         updateCallable = new boolean[joinSpan];
134         deleteCallable = new boolean[joinSpan];
135         customSQLInsert[0] = persistentClass.getCustomSQLInsert();
136         customSQLUpdate[0] = persistentClass.getCustomSQLUpdate();
137         customSQLDelete[0] = persistentClass.getCustomSQLDelete();
138         insertCallable[0] = persistentClass.isCustomInsertCallable();
139         updateCallable[0] = persistentClass.isCustomUpdateCallable();
140         deleteCallable[0] = persistentClass.isCustomDeleteCallable();
141
142         // JOINS
143

144         Iterator JavaDoc joinIter = persistentClass.getJoinClosureIterator();
145         int j=1;
146         while ( joinIter.hasNext() ) {
147             Join join = (Join) joinIter.next();
148             qualifiedTableNames[j] = join.getTable().getQualifiedName(
149                     factory.getDialect(),
150                     factory.getSettings().getDefaultCatalogName(),
151                     factory.getSettings().getDefaultSchemaName()
152             );
153             isInverseTable[j] = join.isInverse();
154             isNullableTable[j] = join.isOptional();
155             cascadeDeleteEnabled[j] = join.getKey().isCascadeDeleteEnabled() &&
156                 factory.getDialect().supportsCascadeDelete();
157
158             customSQLInsert[j] = join.getCustomSQLInsert();
159             customSQLUpdate[j] = join.getCustomSQLUpdate();
160             customSQLDelete[j] = join.getCustomSQLDelete();
161             insertCallable[j] = join.isCustomInsertCallable();
162             updateCallable[j] = join.isCustomUpdateCallable();
163             deleteCallable[j] = join.isCustomDeleteCallable();
164
165             Iterator JavaDoc iter = join.getKey().getColumnIterator();
166             keyColumnNames[j] = new String JavaDoc[ join.getKey().getColumnSpan() ];
167             int i = 0;
168             while ( iter.hasNext() ) {
169                 Column col = (Column) iter.next();
170                 keyColumnNames[j][i++] = col.getQuotedName( factory.getDialect() );
171             }
172
173             j++;
174         }
175
176         constraintOrderedTableNames = new String JavaDoc[qualifiedTableNames.length];
177         constraintOrderedKeyColumnNames = new String JavaDoc[qualifiedTableNames.length][];
178         for ( int i = qualifiedTableNames.length - 1, position = 0; i >= 0; i--, position++ ) {
179             constraintOrderedTableNames[position] = qualifiedTableNames[i];
180             constraintOrderedKeyColumnNames[position] = keyColumnNames[i];
181         }
182
183         spaces = ArrayHelper.join(
184                 qualifiedTableNames,
185                 ArrayHelper.toStringArray( persistentClass.getSynchronizedTables() )
186         );
187         
188         final boolean lazyAvailable = isInstrumented(EntityMode.POJO);
189
190         boolean hasDeferred = false;
191         ArrayList JavaDoc subclassTables = new ArrayList JavaDoc();
192         ArrayList JavaDoc joinKeyColumns = new ArrayList JavaDoc();
193         ArrayList JavaDoc isConcretes = new ArrayList JavaDoc();
194         ArrayList JavaDoc isDeferreds = new ArrayList JavaDoc();
195         ArrayList JavaDoc isInverses = new ArrayList JavaDoc();
196         ArrayList JavaDoc isNullables = new ArrayList JavaDoc();
197         ArrayList JavaDoc isLazies = new ArrayList JavaDoc();
198         subclassTables.add( qualifiedTableNames[0] );
199         joinKeyColumns.add( getIdentifierColumnNames() );
200         isConcretes.add(Boolean.TRUE);
201         isDeferreds.add(Boolean.FALSE);
202         isInverses.add(Boolean.FALSE);
203         isNullables.add(Boolean.FALSE);
204         isLazies.add(Boolean.FALSE);
205         joinIter = persistentClass.getSubclassJoinClosureIterator();
206         while ( joinIter.hasNext() ) {
207             Join join = (Join) joinIter.next();
208             isConcretes.add( new Boolean JavaDoc( persistentClass.isClassOrSuperclassJoin(join) ) );
209             isDeferreds.add( new Boolean JavaDoc( join.isSequentialSelect() ) );
210             isInverses.add( new Boolean JavaDoc( join.isInverse() ) );
211             isNullables.add( new Boolean JavaDoc( join.isOptional() ) );
212             isLazies.add( new Boolean JavaDoc( lazyAvailable && join.isLazy() ) );
213             if ( join.isSequentialSelect() && !persistentClass.isClassOrSuperclassJoin(join) ) hasDeferred = true;
214             subclassTables.add( join.getTable().getQualifiedName(
215                     factory.getDialect(),
216                     factory.getSettings().getDefaultCatalogName(),
217                     factory.getSettings().getDefaultSchemaName()
218             ) );
219             Iterator JavaDoc iter = join.getKey().getColumnIterator();
220             String JavaDoc[] keyCols = new String JavaDoc[ join.getKey().getColumnSpan() ];
221             int i = 0;
222             while ( iter.hasNext() ) {
223                 Column col = (Column) iter.next();
224                 keyCols[i++] = col.getQuotedName( factory.getDialect() );
225             }
226             joinKeyColumns.add(keyCols);
227         }
228         
229         subclassTableSequentialSelect = ArrayHelper.toBooleanArray(isDeferreds);
230         subclassTableNameClosure = ArrayHelper.toStringArray(subclassTables);
231         subclassTableIsLazyClosure = ArrayHelper.toBooleanArray(isLazies);
232         subclassTableKeyColumnClosure = ArrayHelper.to2DStringArray(joinKeyColumns);
233         isClassOrSuperclassTable = ArrayHelper.toBooleanArray(isConcretes);
234         isInverseSubclassTable = ArrayHelper.toBooleanArray(isInverses);
235         isNullableSubclassTable = ArrayHelper.toBooleanArray(isNullables);
236         hasSequentialSelects = hasDeferred;
237
238         // DISCRIMINATOR
239

240         final Object JavaDoc discriminatorValue;
241         if ( persistentClass.isPolymorphic() ) {
242             Value discrimValue = persistentClass.getDiscriminator();
243             if (discrimValue==null) {
244                 throw new MappingException("discriminator mapping required for single table polymorphic persistence");
245             }
246             forceDiscriminator = persistentClass.isForceDiscriminator();
247             Selectable selectable = (Selectable) discrimValue.getColumnIterator().next();
248             if ( discrimValue.hasFormula() ) {
249                 Formula formula = (Formula) selectable;
250                 discriminatorFormula = formula.getFormula();
251                 discriminatorFormulaTemplate = formula.getTemplate( factory.getDialect() );
252                 discriminatorColumnName = null;
253                 discriminatorAlias = "clazz_";
254             }
255             else {
256                 Column column = (Column) selectable;
257                 discriminatorColumnName = column.getQuotedName( factory.getDialect() );
258                 discriminatorAlias = column.getAlias( factory.getDialect(), persistentClass.getRootTable() );
259                 discriminatorFormula = null;
260                 discriminatorFormulaTemplate = null;
261             }
262             discriminatorType = persistentClass.getDiscriminator().getType();
263             if ( persistentClass.isDiscriminatorValueNull() ) {
264                 discriminatorValue = NULL_DISCRIMINATOR;
265                 discriminatorSQLValue = InFragment.NULL;
266                 discriminatorInsertable = false;
267             }
268             else if ( persistentClass.isDiscriminatorValueNotNull() ) {
269                 discriminatorValue = NOT_NULL_DISCRIMINATOR;
270                 discriminatorSQLValue = InFragment.NOT_NULL;
271                 discriminatorInsertable = false;
272             }
273             else {
274                 discriminatorInsertable = persistentClass.isDiscriminatorInsertable() && !discrimValue.hasFormula();
275                 try {
276                     DiscriminatorType dtype = (DiscriminatorType) discriminatorType;
277                     discriminatorValue = dtype.stringToObject( persistentClass.getDiscriminatorValue() );
278                     discriminatorSQLValue = dtype.objectToSQLString(discriminatorValue);
279                 }
280                 catch (ClassCastException JavaDoc cce) {
281                     throw new MappingException("Illegal discriminator type: " + discriminatorType.getName() );
282                 }
283                 catch (Exception JavaDoc e) {
284                     throw new MappingException("Could not format discriminator value to SQL string", e);
285                 }
286             }
287         }
288         else {
289             forceDiscriminator = false;
290             discriminatorInsertable = false;
291             discriminatorColumnName = null;
292             discriminatorAlias = null;
293             discriminatorType = null;
294             discriminatorValue = null;
295             discriminatorSQLValue = null;
296             discriminatorFormula = null;
297             discriminatorFormulaTemplate = null;
298         }
299
300         // PROPERTIES
301

302         propertyTableNumbers = new int[ getPropertySpan() ];
303         Iterator JavaDoc iter = persistentClass.getPropertyClosureIterator();
304         int i=0;
305         while( iter.hasNext() ) {
306             Property prop = (Property) iter.next();
307             propertyTableNumbers[i++] = persistentClass.getJoinNumber(prop);
308
309         }
310
311         //TODO: code duplication with JoinedSubclassEntityPersister
312

313         ArrayList JavaDoc columnJoinNumbers = new ArrayList JavaDoc();
314         ArrayList JavaDoc formulaJoinedNumbers = new ArrayList JavaDoc();
315         ArrayList JavaDoc propertyJoinNumbers = new ArrayList JavaDoc();
316         
317         iter = persistentClass.getSubclassPropertyClosureIterator();
318         while ( iter.hasNext() ) {
319             Property prop = (Property) iter.next();
320             Integer JavaDoc join = new Integer JavaDoc( persistentClass.getJoinNumber(prop) );
321             propertyJoinNumbers.add(join);
322
323             //propertyTableNumbersByName.put( prop.getName(), join );
324
propertyTableNumbersByNameAndSubclass.put(
325                     prop.getPersistentClass().getEntityName() + '.' + prop.getName(),
326                     join
327             );
328
329             Iterator JavaDoc citer = prop.getColumnIterator();
330             while ( citer.hasNext() ) {
331                 Selectable thing = (Selectable) citer.next();
332                 if ( thing.isFormula() ) {
333                     formulaJoinedNumbers.add(join);
334                 }
335                 else {
336                     columnJoinNumbers.add(join);
337                 }
338             }
339         }
340         subclassColumnTableNumberClosure = ArrayHelper.toIntArray(columnJoinNumbers);
341         subclassFormulaTableNumberClosure = ArrayHelper.toIntArray(formulaJoinedNumbers);
342         subclassPropertyTableNumberClosure = ArrayHelper.toIntArray(propertyJoinNumbers);
343
344         int subclassSpan = persistentClass.getSubclassSpan() + 1;
345         subclassClosure = new String JavaDoc[subclassSpan];
346         subclassClosure[0] = getEntityName();
347         if ( persistentClass.isPolymorphic() ) {
348             subclassesByDiscriminatorValue.put( discriminatorValue, getEntityName() );
349         }
350
351         // SUBCLASSES
352
if ( persistentClass.isPolymorphic() ) {
353             iter = persistentClass.getSubclassIterator();
354             int k=1;
355             while ( iter.hasNext() ) {
356                 Subclass sc = (Subclass) iter.next();
357                 subclassClosure[k++] = sc.getEntityName();
358                 if ( sc.isDiscriminatorValueNull() ) {
359                     subclassesByDiscriminatorValue.put( NULL_DISCRIMINATOR, sc.getEntityName() );
360                 }
361                 else if ( sc.isDiscriminatorValueNotNull() ) {
362                     subclassesByDiscriminatorValue.put( NOT_NULL_DISCRIMINATOR, sc.getEntityName() );
363                 }
364                 else {
365                     try {
366                         DiscriminatorType dtype = (DiscriminatorType) discriminatorType;
367                         subclassesByDiscriminatorValue.put(
368                             dtype.stringToObject( sc.getDiscriminatorValue() ),
369                             sc.getEntityName()
370                         );
371                     }
372                     catch (ClassCastException JavaDoc cce) {
373                         throw new MappingException("Illegal discriminator type: " + discriminatorType.getName() );
374                     }
375                     catch (Exception JavaDoc e) {
376                         throw new MappingException("Error parsing discriminator value", e);
377                     }
378                 }
379             }
380         }
381
382         initLockers();
383
384         initSubclassPropertyAliasesMap(persistentClass);
385         
386         postConstruct(mapping);
387
388     }
389
390     protected boolean isInverseTable(int j) {
391         return isInverseTable[j];
392     }
393
394     protected boolean isInverseSubclassTable(int j) {
395         return isInverseSubclassTable[j];
396     }
397
398     public String JavaDoc getDiscriminatorColumnName() {
399         return discriminatorColumnName;
400     }
401
402     protected String JavaDoc getDiscriminatorAlias() {
403         return discriminatorAlias;
404     }
405
406     protected String JavaDoc getDiscriminatorFormulaTemplate() {
407         return discriminatorFormulaTemplate;
408     }
409
410     public String JavaDoc getTableName() {
411         return qualifiedTableNames[0];
412     }
413
414     public Type getDiscriminatorType() {
415         return discriminatorType;
416     }
417
418     public String JavaDoc getDiscriminatorSQLValue() {
419         return discriminatorSQLValue;
420     }
421
422     public String JavaDoc[] getSubclassClosure() {
423         return subclassClosure;
424     }
425
426     public String JavaDoc getSubclassForDiscriminatorValue(Object JavaDoc value) {
427         if (value==null) {
428             return (String JavaDoc) subclassesByDiscriminatorValue.get(NULL_DISCRIMINATOR);
429         }
430         else {
431             String JavaDoc result = (String JavaDoc) subclassesByDiscriminatorValue.get(value);
432             if (result==null) result = (String JavaDoc) subclassesByDiscriminatorValue.get(NOT_NULL_DISCRIMINATOR);
433             return result;
434         }
435     }
436
437     public Serializable JavaDoc[] getPropertySpaces() {
438         return spaces;
439     }
440
441     //Access cached SQL
442

443     protected boolean isDiscriminatorFormula() {
444         return discriminatorColumnName==null;
445     }
446
447     protected String JavaDoc getDiscriminatorFormula() {
448         return discriminatorFormula;
449     }
450
451     protected String JavaDoc getTableName(int j) {
452         return qualifiedTableNames[j];
453     }
454     
455     protected String JavaDoc[] getKeyColumns(int j) {
456         return keyColumnNames[j];
457     }
458     
459     protected boolean isTableCascadeDeleteEnabled(int j) {
460         return cascadeDeleteEnabled[j];
461     }
462     
463     protected boolean isPropertyOfTable(int property, int j) {
464         return propertyTableNumbers[property]==j;
465     }
466
467     protected boolean isSubclassTableSequentialSelect(int j) {
468         return subclassTableSequentialSelect[j] && !isClassOrSuperclassTable[j];
469     }
470     
471     // Execute the SQL:
472

473     public String JavaDoc fromTableFragment(String JavaDoc name) {
474         return getTableName() + ' ' + name;
475     }
476
477     public String JavaDoc filterFragment(String JavaDoc alias) throws MappingException {
478         String JavaDoc result = discriminatorFilterFragment(alias);
479         if ( hasWhere() ) result += " and " + getSQLWhereString(alias);
480         return result;
481     }
482     
483     public String JavaDoc oneToManyFilterFragment(String JavaDoc alias) throws MappingException {
484         return forceDiscriminator ?
485             discriminatorFilterFragment(alias) :
486             "";
487     }
488
489     private String JavaDoc discriminatorFilterFragment(String JavaDoc alias) throws MappingException {
490         if ( needsDiscriminator() ) {
491             InFragment frag = new InFragment();
492
493             if ( isDiscriminatorFormula() ) {
494                 frag.setFormula( alias, getDiscriminatorFormulaTemplate() );
495             }
496             else {
497                 frag.setColumn( alias, getDiscriminatorColumnName() );
498             }
499
500             String JavaDoc[] subclasses = getSubclassClosure();
501             for ( int i=0; i<subclasses.length; i++ ) {
502                 final Queryable queryable = (Queryable) getFactory().getEntityPersister( subclasses[i] );
503                 if ( !queryable.isAbstract() ) frag.addValue( queryable.getDiscriminatorSQLValue() );
504             }
505
506             StringBuffer JavaDoc buf = new StringBuffer JavaDoc(50)
507                 .append(" and ")
508                 .append( frag.toFragmentString() );
509
510             return buf.toString();
511         }
512         else {
513             return "";
514         }
515     }
516
517     private boolean needsDiscriminator() {
518         return forceDiscriminator || isInherited();
519     }
520
521     public String JavaDoc getSubclassPropertyTableName(int i) {
522         return subclassTableNameClosure[ subclassPropertyTableNumberClosure[i] ];
523     }
524
525     protected void addDiscriminatorToSelect(SelectFragment select, String JavaDoc name, String JavaDoc suffix) {
526         if ( isDiscriminatorFormula() ) {
527             select.addFormula( name, getDiscriminatorFormulaTemplate(), getDiscriminatorAlias() );
528         }
529         else {
530             select.addColumn( name, getDiscriminatorColumnName(), getDiscriminatorAlias() );
531         }
532     }
533     
534     protected int[] getPropertyTableNumbersInSelect() {
535         return propertyTableNumbers;
536     }
537
538     protected int getSubclassPropertyTableNumber(int i) {
539         return subclassPropertyTableNumberClosure[i];
540     }
541
542     public int getTableSpan() {
543         return joinSpan;
544     }
545
546     protected void addDiscriminatorToInsert(Insert insert) {
547
548         if (discriminatorInsertable) {
549             insert.addColumn( getDiscriminatorColumnName(), discriminatorSQLValue );
550         }
551
552     }
553
554     protected int[] getSubclassColumnTableNumberClosure() {
555         return subclassColumnTableNumberClosure;
556     }
557
558     protected int[] getSubclassFormulaTableNumberClosure() {
559         return subclassFormulaTableNumberClosure;
560     }
561
562     protected int[] getPropertyTableNumbers() {
563         return propertyTableNumbers;
564     }
565         
566     protected boolean isSubclassPropertyDeferred(String JavaDoc propertyName, String JavaDoc entityName) {
567         return hasSequentialSelects &&
568             isSubclassTableSequentialSelect( getSubclassPropertyTableNumber(propertyName, entityName) );
569     }
570     
571     public boolean hasSequentialSelect() {
572         return hasSequentialSelects;
573     }
574     
575     private int getSubclassPropertyTableNumber(String JavaDoc propertyName, String JavaDoc entityName) {
576         Type type = propertyMapping.toType(propertyName);
577         if ( type.isAssociationType() && ( (AssociationType) type ).useLHSPrimaryKey() ) return 0;
578         final Integer JavaDoc tabnum = (Integer JavaDoc) propertyTableNumbersByNameAndSubclass.get(entityName + '.' + propertyName);
579         return tabnum==null ? 0 : tabnum.intValue();
580     }
581     
582     protected String JavaDoc getSequentialSelect(String JavaDoc entityName) {
583         return (String JavaDoc) sequentialSelectStringsByEntityName.get(entityName);
584     }
585
586     private String JavaDoc generateSequentialSelect(Loadable persister) {
587         //if ( this==persister || !hasSequentialSelects ) return null;
588

589         //note that this method could easily be moved up to BasicEntityPersister,
590
//if we ever needed to reuse it from other subclasses
591

592         //figure out which tables need to be fetched
593
BasicEntityPersister subclassPersister = (BasicEntityPersister) persister;
594         HashSet JavaDoc tableNumbers = new HashSet JavaDoc();
595         String JavaDoc[] props = subclassPersister.getPropertyNames();
596         String JavaDoc[] classes = subclassPersister.getPropertySubclassNames();
597         for ( int i=0; i<props.length; i++ ) {
598             int propTableNumber = getSubclassPropertyTableNumber( props[i], classes[i] );
599             if ( isSubclassTableSequentialSelect(propTableNumber) && !isSubclassTableLazy(propTableNumber) ) {
600                 tableNumbers.add( new Integer JavaDoc(propTableNumber) );
601             }
602         }
603         if ( tableNumbers.isEmpty() ) return null;
604         
605         //figure out which columns are needed
606
ArrayList JavaDoc columnNumbers = new ArrayList JavaDoc();
607         final int[] columnTableNumbers = getSubclassColumnTableNumberClosure();
608         for ( int i=0; i<getSubclassColumnClosure().length; i++ ) {
609             if ( tableNumbers.contains( new Integer JavaDoc( columnTableNumbers[i] ) ) ) {
610                 columnNumbers.add( new Integer JavaDoc(i) );
611             }
612         }
613         
614         //figure out which formulas are needed
615
ArrayList JavaDoc formulaNumbers = new ArrayList JavaDoc();
616         final int[] formulaTableNumbers = getSubclassColumnTableNumberClosure();
617         for ( int i=0; i<getSubclassFormulaTemplateClosure().length; i++ ) {
618             if ( tableNumbers.contains( new Integer JavaDoc( formulaTableNumbers[i] ) ) ) {
619                 formulaNumbers.add( new Integer JavaDoc(i) );
620             }
621         }
622         
623         //render the SQL
624
return renderSelect(
625             ArrayHelper.toIntArray(tableNumbers),
626             ArrayHelper.toIntArray(columnNumbers),
627             ArrayHelper.toIntArray(formulaNumbers)
628         );
629     }
630         
631         
632     protected String JavaDoc[] getSubclassTableKeyColumns(int j) {
633         return subclassTableKeyColumnClosure[j];
634     }
635
636     public String JavaDoc getSubclassTableName(int j) {
637         return subclassTableNameClosure[j];
638     }
639
640     public int getSubclassTableSpan() {
641         return subclassTableNameClosure.length;
642     }
643
644     protected boolean isClassOrSuperclassTable(int j) {
645         return isClassOrSuperclassTable[j];
646     }
647
648     protected boolean isSubclassTableLazy(int j) {
649         return subclassTableIsLazyClosure[j];
650     }
651     
652     protected boolean isNullableTable(int j) {
653         return isNullableTable[j];
654     }
655     
656     protected boolean isNullableSubclassTable(int j) {
657         return isNullableSubclassTable[j];
658     }
659
660     public String JavaDoc getPropertyTableName(String JavaDoc propertyName) {
661         Integer JavaDoc index = getEntityMetamodel().getPropertyIndexOrNull(propertyName);
662         if (index==null) return null;
663         return qualifiedTableNames[ propertyTableNumbers[ index.intValue() ] ];
664     }
665     
666     public void postInstantiate() {
667         super.postInstantiate();
668         if (hasSequentialSelects) {
669             String JavaDoc[] entityNames = getSubclassClosure();
670             for ( int i=1; i<entityNames.length; i++ ) {
671                 Loadable loadable = (Loadable) getFactory().getEntityPersister( entityNames[i] );
672                 if ( !loadable.isAbstract() ) { //perhaps not really necessary...
673
String JavaDoc sequentialSelect = generateSequentialSelect(loadable);
674                     sequentialSelectStringsByEntityName.put( entityNames[i], sequentialSelect );
675                 }
676             }
677         }
678     }
679
680     public boolean isMultiTable() {
681         return getTableSpan() > 1;
682     }
683
684     public String JavaDoc[] getConstraintOrderedTableNameClosure() {
685         return constraintOrderedTableNames;
686     }
687
688     public String JavaDoc[][] getContraintOrderedTableKeyColumnClosure() {
689         return constraintOrderedKeyColumnNames;
690     }
691 }
692
Popular Tags