KickJava   Java API By Example, From Geeks To Geeks.

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


1 //$Id: BasicEntityPersister.java,v 1.54 2005/07/21 01:11:52 oneovthafew Exp $
2
package org.hibernate.persister.entity;
3
4 import java.io.Serializable JavaDoc;
5 import java.sql.CallableStatement JavaDoc;
6 import java.sql.PreparedStatement JavaDoc;
7 import java.sql.ResultSet JavaDoc;
8 import java.sql.SQLException JavaDoc;
9 import java.sql.Types JavaDoc;
10 import java.util.ArrayList JavaDoc;
11 import java.util.Arrays JavaDoc;
12 import java.util.HashMap JavaDoc;
13 import java.util.HashSet JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.Map JavaDoc;
16 import java.util.Set JavaDoc;
17
18 import net.sf.cglib.transform.impl.InterceptFieldEnabled;
19
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22 import org.hibernate.AssertionFailure;
23 import org.hibernate.EntityMode;
24 import org.hibernate.FetchMode;
25 import org.hibernate.HibernateException;
26 import org.hibernate.LockMode;
27 import org.hibernate.MappingException;
28 import org.hibernate.QueryException;
29 import org.hibernate.StaleObjectStateException;
30 import org.hibernate.cache.CacheConcurrencyStrategy;
31 import org.hibernate.cache.CacheKey;
32 import org.hibernate.cache.entry.CacheEntryStructure;
33 import org.hibernate.cache.entry.StructuredCacheEntry;
34 import org.hibernate.cache.entry.UnstructuredCacheEntry;
35 import org.hibernate.engine.CascadeStyle;
36 import org.hibernate.engine.EntityEntry;
37 import org.hibernate.engine.Mapping;
38 import org.hibernate.engine.SessionFactoryImplementor;
39 import org.hibernate.engine.SessionImplementor;
40 import org.hibernate.engine.Versioning;
41 import org.hibernate.exception.JDBCExceptionHelper;
42 import org.hibernate.id.IdentifierGenerator;
43 import org.hibernate.id.IdentifierGeneratorFactory;
44 import org.hibernate.id.PostInsertIdentifierGenerator;
45 import org.hibernate.id.PostInsertIdentityPersister;
46 import org.hibernate.intercept.FieldInterceptor;
47 import org.hibernate.intercept.LazyPropertyInitializer;
48 import org.hibernate.loader.entity.BatchingEntityLoader;
49 import org.hibernate.loader.entity.EntityLoader;
50 import org.hibernate.loader.entity.UniqueEntityLoader;
51 import org.hibernate.mapping.Column;
52 import org.hibernate.mapping.Component;
53 import org.hibernate.mapping.PersistentClass;
54 import org.hibernate.mapping.Property;
55 import org.hibernate.mapping.Selectable;
56 import org.hibernate.metadata.ClassMetadata;
57 import org.hibernate.pretty.MessageHelper;
58 import org.hibernate.property.BackrefPropertyAccessor;
59 import org.hibernate.sql.Alias;
60 import org.hibernate.sql.Delete;
61 import org.hibernate.sql.Insert;
62 import org.hibernate.sql.JoinFragment;
63 import org.hibernate.sql.Select;
64 import org.hibernate.sql.SelectFragment;
65 import org.hibernate.sql.SimpleSelect;
66 import org.hibernate.sql.Template;
67 import org.hibernate.sql.Update;
68 import org.hibernate.tuple.EntityMetamodel;
69 import org.hibernate.tuple.EntityTuplizer;
70 import org.hibernate.tuple.Tuplizer;
71 import org.hibernate.type.AbstractComponentType;
72 import org.hibernate.type.AssociationType;
73 import org.hibernate.type.EntityType;
74 import org.hibernate.type.Type;
75 import org.hibernate.type.TypeFactory;
76 import org.hibernate.type.VersionType;
77 import org.hibernate.util.ArrayHelper;
78 import org.hibernate.util.CollectionHelper;
79 import org.hibernate.util.FilterHelper;
80 import org.hibernate.util.GetGeneratedKeysHelper;
81 import org.hibernate.util.StringHelper;
82
83 /**
84  * Basic functionality for persisting an entity via JDBC
85  * through either generated or custom SQL
86  *
87  * @author Gavin King
88  */

89 public abstract class BasicEntityPersister
90         implements OuterJoinLoadable, Queryable, ClassMetadata, UniqueKeyLoadable,
91         SQLLoadable, LazyPropertyInitializer, PostInsertIdentityPersister {
92
93     private static final Log log = LogFactory.getLog( BasicEntityPersister.class );
94
95     public static final String JavaDoc ENTITY_CLASS = "class";
96
97     // moved up from AbstractEntityPersister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
98
private final SessionFactoryImplementor factory;
99     private final CacheConcurrencyStrategy cache;
100     private final CacheEntryStructure cacheEntryStructure;
101     private final EntityMetamodel entityMetamodel;
102     private final Map JavaDoc entityNameBySubclass = new HashMap JavaDoc();
103     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
104

105     private final String JavaDoc[] rootTableKeyColumnNames;
106     private final String JavaDoc[] identifierAliases;
107     private final int identifierColumnSpan;
108     private final String JavaDoc versionColumnName;
109     private final boolean hasFormulaProperties;
110     private final int batchSize;
111     private final boolean hasSubselectLoadableCollections;
112     protected final String JavaDoc rowIdName;
113
114     private final Set JavaDoc lazyProperties;
115
116     // The optional SQL string defined in the where attribute
117
private final String JavaDoc sqlWhereString;
118     private final String JavaDoc sqlWhereStringTemplate;
119
120     //information about properties of this class,
121
//including inherited properties
122
//(only really needed for updatable/insertable properties)
123
private final int[] propertyColumnSpans;
124     private final String JavaDoc[] propertySubclassNames;
125     private final String JavaDoc[][] propertyColumnAliases;
126     private final String JavaDoc[][] propertyColumnNames;
127     private final String JavaDoc[][] propertyColumnFormulaTemplates;
128     private final boolean[][] propertyColumnUpdateable;
129     private final boolean[][] propertyColumnInsertable;
130     private final boolean[] propertyUniqueness;
131     private final boolean[] propertySelectable;
132
133     //information about lazy properties of this class
134
private final String JavaDoc[] lazyPropertyNames;
135     private final int[] lazyPropertyNumbers;
136     private final Type[] lazyPropertyTypes;
137     private final String JavaDoc[][] lazyPropertyColumnAliases;
138
139     //information about all properties in class hierarchy
140
private final String JavaDoc[] subclassPropertyNameClosure;
141     private final String JavaDoc[] subclassPropertySubclassNameClosure;
142     private final Type[] subclassPropertyTypeClosure;
143     private final String JavaDoc[][] subclassPropertyFormulaTemplateClosure;
144     private final String JavaDoc[][] subclassPropertyColumnNameClosure;
145     private final FetchMode[] subclassPropertyFetchModeClosure;
146     private final boolean[] subclassPropertyNullabilityClosure;
147     private final boolean[] propertyDefinedOnSubclass;
148     private final int[][] subclassPropertyColumnNumberClosure;
149     private final int[][] subclassPropertyFormulaNumberClosure;
150
151     //information about all columns/formulas in class hierarchy
152
private final String JavaDoc[] subclassColumnClosure;
153     private final boolean[] subclassColumnLazyClosure;
154     private final String JavaDoc[] subclassColumnAliasClosure;
155     private final boolean[] subclassColumnSelectableClosure;
156     private final String JavaDoc[] subclassFormulaClosure;
157     private final String JavaDoc[] subclassFormulaTemplateClosure;
158     private final String JavaDoc[] subclassFormulaAliasClosure;
159     private final boolean[] subclassFormulaLazyClosure;
160     
161     // dynamic filters attached to the class-level
162
private final FilterHelper filterHelper;
163
164     private final Map JavaDoc uniqueKeyLoaders = new HashMap JavaDoc();
165     private final Map JavaDoc lockers = new HashMap JavaDoc();
166     private final Map JavaDoc loaders = new HashMap JavaDoc();
167
168     // SQL strings
169
private String JavaDoc sqlVersionSelectString;
170     private String JavaDoc sqlSnapshotSelectString;
171     private String JavaDoc sqlLazySelectString;
172
173     private String JavaDoc sqlIdentityInsertString;
174     private String JavaDoc sqlUpdateByRowIdString;
175     private String JavaDoc sqlLazyUpdateByRowIdString;
176
177     private String JavaDoc[] sqlDeleteStrings;
178     private String JavaDoc[] sqlInsertStrings;
179     private String JavaDoc[] sqlUpdateStrings;
180     private String JavaDoc[] sqlLazyUpdateStrings;
181
182     //Custom SQL (would be better if these were private)
183
protected boolean[] insertCallable;
184     protected boolean[] updateCallable;
185     protected boolean[] deleteCallable;
186     protected String JavaDoc[] customSQLInsert;
187     protected String JavaDoc[] customSQLUpdate;
188     protected String JavaDoc[] customSQLDelete;
189
190     private boolean[] tableHasColumns;
191
192     private final String JavaDoc loaderName;
193
194     private UniqueEntityLoader queryLoader;
195
196     private final String JavaDoc temporaryIdTableName;
197     private final String JavaDoc temporaryIdTableDDL;
198
199     private final Map JavaDoc subclassPropertyAliases = new HashMap JavaDoc();
200     private final Map JavaDoc subclassPropertyColumnNames = new HashMap JavaDoc();
201
202     protected final BasicEntityPropertyMapping propertyMapping;
203
204     protected void addDiscriminatorToInsert(Insert insert) {}
205
206     protected void addDiscriminatorToSelect(SelectFragment select, String JavaDoc name, String JavaDoc suffix) {}
207
208     protected abstract int[] getSubclassColumnTableNumberClosure();
209
210     protected abstract int[] getSubclassFormulaTableNumberClosure();
211
212     public abstract String JavaDoc getSubclassTableName(int j);
213
214     protected abstract String JavaDoc[] getSubclassTableKeyColumns(int j);
215
216     protected abstract boolean isClassOrSuperclassTable(int j);
217
218     protected abstract int getSubclassTableSpan();
219
220     protected abstract int getTableSpan();
221
222     protected abstract boolean isTableCascadeDeleteEnabled(int j);
223
224     protected abstract String JavaDoc getTableName(int j);
225
226     protected abstract String JavaDoc[] getKeyColumns(int j);
227
228     protected abstract boolean isPropertyOfTable(int property, int j);
229
230     protected abstract int[] getPropertyTableNumbersInSelect();
231
232     protected abstract int[] getPropertyTableNumbers();
233
234     protected abstract int getSubclassPropertyTableNumber(int i);
235     
236     protected abstract String JavaDoc filterFragment(String JavaDoc alias) throws MappingException;
237
238     private static final String JavaDoc DISCRIMINATOR_ALIAS = "clazz_";
239     
240     public String JavaDoc getDiscriminatorColumnName() {
241         return DISCRIMINATOR_ALIAS;
242     }
243
244     protected String JavaDoc getDiscriminatorAlias() {
245         return DISCRIMINATOR_ALIAS;
246     }
247
248     protected String JavaDoc getDiscriminatorFormulaTemplate() {
249         return null;
250     }
251
252     protected boolean isInverseTable(int j) {
253         return false;
254     }
255
256     protected boolean isNullableTable(int j) {
257         return false;
258     }
259
260     protected boolean isNullableSubclassTable(int j) {
261         return false;
262     }
263
264     protected boolean isInverseSubclassTable(int j) {
265         return false;
266     }
267     
268     public boolean isSubclassEntityName(String JavaDoc entityName) {
269         return entityMetamodel.getSubclassEntityNames().contains(entityName);
270     }
271
272     private boolean[] getTableHasColumns() {
273         return tableHasColumns;
274     }
275
276     public String JavaDoc[] getRootTableKeyColumnNames() {
277         return rootTableKeyColumnNames;
278     }
279     
280     protected String JavaDoc[] getSQLUpdateByRowIdStrings() {
281         if ( sqlUpdateByRowIdString == null ) {
282             throw new AssertionFailure( "no update by row id" );
283         }
284         String JavaDoc[] result = new String JavaDoc[getTableSpan()];
285         result[0] = sqlUpdateByRowIdString;
286         for ( int i = 1; i < getTableSpan(); i++ ) result[i] = sqlUpdateStrings[i];
287         return result;
288     }
289
290     protected String JavaDoc[] getSQLLazyUpdateByRowIdStrings() {
291         if ( sqlLazyUpdateByRowIdString == null ) {
292             throw new AssertionFailure( "no update by row id" );
293         }
294         String JavaDoc[] result = new String JavaDoc[getTableSpan()];
295         result[0] = sqlLazyUpdateByRowIdString;
296         for ( int i = 1; i < getTableSpan(); i++ ) result[i] = sqlLazyUpdateStrings[i];
297         return result;
298     }
299
300     protected String JavaDoc getSQLSnapshotSelectString() {
301         return sqlSnapshotSelectString;
302     }
303
304     protected String JavaDoc getSQLLazySelectString() {
305         return sqlLazySelectString;
306     }
307
308     protected String JavaDoc[] getSQLDeleteStrings() {
309         return sqlDeleteStrings;
310     }
311
312     protected String JavaDoc[] getSQLInsertStrings() {
313         return sqlInsertStrings;
314     }
315
316     protected String JavaDoc[] getSQLUpdateStrings() {
317         return sqlUpdateStrings;
318     }
319
320     protected String JavaDoc[] getSQLLazyUpdateStrings() {
321         return sqlLazyUpdateStrings;
322     }
323
324     /**
325      * The query that inserts a row, letting the database generate an id
326      */

327     protected String JavaDoc getSQLIdentityInsertString() {
328         return sqlIdentityInsertString;
329     }
330
331     protected String JavaDoc getVersionSelectString() {
332         return sqlVersionSelectString;
333     }
334
335     protected boolean isInsertCallable(int j) {
336         return insertCallable[j];
337     }
338
339     protected boolean isUpdateCallable(int j) {
340         return updateCallable[j];
341     }
342
343     protected boolean isDeleteCallable(int j) {
344         return deleteCallable[j];
345     }
346
347     protected boolean isSubclassPropertyDeferred(String JavaDoc propertyName, String JavaDoc entityName) {
348         return false;
349     }
350
351     protected boolean isSubclassTableSequentialSelect(int j) {
352         return false;
353     }
354
355     public boolean hasSequentialSelect() {
356         return false;
357     }
358
359     /**
360      * Decide which tables need to be updated
361      */

362     protected boolean[] getTableUpdateNeeded(final int[] dirtyProperties, boolean hasDirtyCollection) {
363
364         if ( dirtyProperties == null ) {
365             return getTableHasColumns(); // for objects that came in via update()
366
}
367         else {
368             boolean[] updateability = getPropertyUpdateability();
369             int[] propertyTableNumbers = getPropertyTableNumbers();
370             boolean[] tableUpdateNeeded = new boolean[ getTableSpan() ];
371             for ( int i = 0; i < dirtyProperties.length; i++ ) {
372                 int property = dirtyProperties[i];
373                 int table = propertyTableNumbers[property];
374                 tableUpdateNeeded[table] = tableUpdateNeeded[table] ||
375                         ( getPropertyColumnSpan(property) > 0 && updateability[property] );
376             }
377             if ( isVersioned() ) {
378                 tableUpdateNeeded[0] = tableUpdateNeeded[0] ||
379                     Versioning.isVersionIncrementRequired( dirtyProperties, hasDirtyCollection, getPropertyVersionability() );
380             }
381             return tableUpdateNeeded;
382         }
383     }
384
385     public boolean hasRowId() {
386         return rowIdName != null;
387     }
388
389     public BasicEntityPersister(
390             final PersistentClass persistentClass,
391             final CacheConcurrencyStrategy cache,
392             final SessionFactoryImplementor factory)
393     throws HibernateException {
394
395         // moved up from AbstractEntityPersister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
396
this.factory = factory;
397         this.cache = cache;
398         this.cacheEntryStructure = factory.getSettings().isStructuredCacheEntriesEnabled() ?
399                 (CacheEntryStructure) new StructuredCacheEntry(this) :
400                 (CacheEntryStructure) new UnstructuredCacheEntry();
401
402         this.entityMetamodel = new EntityMetamodel( persistentClass, factory );
403
404         if ( persistentClass.hasPojoRepresentation() ) {
405             //TODO: this is currently specific to pojos, but need to be available for all entity-modes
406
Iterator JavaDoc iter = persistentClass.getSubclassIterator();
407             while ( iter.hasNext() ) {
408                 PersistentClass pc = ( PersistentClass ) iter.next();
409                 entityNameBySubclass.put( pc.getMappedClass(), pc.getEntityName() );
410             }
411         }
412         // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
413

414         int batch = persistentClass.getBatchSize();
415         if (batch==-1) batch = factory.getSettings().getDefaultBatchFetchSize();
416         batchSize = batch;
417         hasSubselectLoadableCollections = persistentClass.hasSubselectLoadableCollections();
418
419         propertyMapping = new BasicEntityPropertyMapping( this );
420
421         // IDENTIFIER
422

423         identifierColumnSpan = persistentClass.getIdentifier().getColumnSpan();
424         rootTableKeyColumnNames = new String JavaDoc[identifierColumnSpan];
425         identifierAliases = new String JavaDoc[identifierColumnSpan];
426
427         rowIdName = persistentClass.getRootTable().getRowId();
428
429         loaderName = persistentClass.getLoaderName();
430
431         Iterator JavaDoc iter = persistentClass.getIdentifier().getColumnIterator();
432         int i = 0;
433         while ( iter.hasNext() ) {
434             Column col = ( Column ) iter.next();
435             rootTableKeyColumnNames[i] = col.getQuotedName( factory.getDialect() );
436             identifierAliases[i] = col.getAlias( factory.getDialect(), persistentClass.getRootTable() );
437             i++;
438         }
439
440         // VERSION
441

442         if ( persistentClass.isVersioned() ) {
443             versionColumnName = ( ( Column ) persistentClass.getVersion().getColumnIterator().next() ).getQuotedName( factory.getDialect() );
444         }
445         else {
446             versionColumnName = null;
447         }
448
449         //WHERE STRING
450

451         sqlWhereString = persistentClass.getWhere();
452         sqlWhereStringTemplate = sqlWhereString == null ?
453                 null :
454                 Template.renderWhereStringTemplate( sqlWhereString, factory.getDialect() );
455
456         // PROPERTIES
457

458         final boolean lazyAvailable = isInstrumented(EntityMode.POJO);
459
460         int hydrateSpan = entityMetamodel.getPropertySpan();
461         propertyColumnSpans = new int[hydrateSpan];
462         propertySubclassNames = new String JavaDoc[hydrateSpan];
463         propertyColumnAliases = new String JavaDoc[hydrateSpan][];
464         propertyColumnNames = new String JavaDoc[hydrateSpan][];
465         propertyColumnFormulaTemplates = new String JavaDoc[hydrateSpan][];
466         propertyUniqueness = new boolean[hydrateSpan];
467         propertySelectable = new boolean[hydrateSpan];
468         propertyColumnUpdateable = new boolean[hydrateSpan][];
469         propertyColumnInsertable = new boolean[hydrateSpan][];
470         HashSet JavaDoc thisClassProperties = new HashSet JavaDoc();
471
472         lazyProperties = new HashSet JavaDoc();
473         ArrayList JavaDoc lazyNames = new ArrayList JavaDoc();
474         ArrayList JavaDoc lazyNumbers = new ArrayList JavaDoc();
475         ArrayList JavaDoc lazyTypes = new ArrayList JavaDoc();
476         ArrayList JavaDoc lazyColAliases = new ArrayList JavaDoc();
477
478         iter = persistentClass.getPropertyClosureIterator();
479         i = 0;
480         boolean foundFormula = false;
481         while ( iter.hasNext() ) {
482             Property prop = ( Property ) iter.next();
483             thisClassProperties.add( prop );
484
485             int span = prop.getColumnSpan();
486             propertyColumnSpans[i] = span;
487             propertySubclassNames[i] = prop.getPersistentClass().getEntityName();
488             String JavaDoc[] colNames = new String JavaDoc[span];
489             String JavaDoc[] colAliases = new String JavaDoc[span];
490             String JavaDoc[] templates = new String JavaDoc[span];
491             Iterator JavaDoc colIter = prop.getColumnIterator();
492             int k = 0;
493             while ( colIter.hasNext() ) {
494                 Selectable thing = ( Selectable ) colIter.next();
495                 colAliases[k] = thing.getAlias( factory.getDialect() , prop.getValue().getTable() );
496                 if ( thing.isFormula() ) {
497                     foundFormula = true;
498                     templates[k] = thing.getTemplate( factory.getDialect() );
499                 }
500                 else {
501                     colNames[k] = thing.getTemplate( factory.getDialect() );
502                 }
503                 k++;
504             }
505             propertyColumnNames[i] = colNames;
506             propertyColumnFormulaTemplates[i] = templates;
507             propertyColumnAliases[i] = colAliases;
508
509             if ( lazyAvailable && prop.isLazy() ) {
510                 lazyProperties.add( prop.getName() );
511                 lazyNames.add( prop.getName() );
512                 lazyNumbers.add( new Integer JavaDoc( i ) );
513                 lazyTypes.add( prop.getValue().getType() );
514                 lazyColAliases.add( colAliases );
515             }
516             
517             propertyColumnUpdateable[i] = prop.getValue().getColumnUpdateability();
518             propertyColumnInsertable[i] = prop.getValue().getColumnInsertability();
519
520             propertySelectable[i] = prop.isSelectable();
521
522             propertyUniqueness[i] = prop.getValue().isAlternateUniqueKey();
523
524             i++;
525
526         }
527         hasFormulaProperties = foundFormula;
528         lazyPropertyColumnAliases = ArrayHelper.to2DStringArray( lazyColAliases );
529         lazyPropertyNames = ArrayHelper.toStringArray( lazyNames );
530         lazyPropertyNumbers = ArrayHelper.toIntArray( lazyNumbers );
531         lazyPropertyTypes = ArrayHelper.toTypeArray( lazyTypes );
532
533         // SUBCLASS PROPERTY CLOSURE
534

535         ArrayList JavaDoc columns = new ArrayList JavaDoc();
536         ArrayList JavaDoc columnsLazy = new ArrayList JavaDoc();
537         ArrayList JavaDoc aliases = new ArrayList JavaDoc();
538         ArrayList JavaDoc formulas = new ArrayList JavaDoc();
539         ArrayList JavaDoc formulaAliases = new ArrayList JavaDoc();
540         ArrayList JavaDoc formulaTemplates = new ArrayList JavaDoc();
541         ArrayList JavaDoc formulasLazy = new ArrayList JavaDoc();
542         ArrayList JavaDoc types = new ArrayList JavaDoc();
543         ArrayList JavaDoc names = new ArrayList JavaDoc();
544         ArrayList JavaDoc classes = new ArrayList JavaDoc();
545         ArrayList JavaDoc templates = new ArrayList JavaDoc();
546         ArrayList JavaDoc propColumns = new ArrayList JavaDoc();
547         ArrayList JavaDoc joinedFetchesList = new ArrayList JavaDoc();
548         ArrayList JavaDoc definedBySubclass = new ArrayList JavaDoc();
549         ArrayList JavaDoc propColumnNumbers = new ArrayList JavaDoc();
550         ArrayList JavaDoc propFormulaNumbers = new ArrayList JavaDoc();
551         ArrayList JavaDoc columnSelectables = new ArrayList JavaDoc();
552         ArrayList JavaDoc propNullables = new ArrayList JavaDoc();
553
554         iter = persistentClass.getSubclassPropertyClosureIterator();
555         while ( iter.hasNext() ) {
556             Property prop = ( Property ) iter.next();
557             names.add( prop.getName() );
558             classes.add( prop.getPersistentClass().getEntityName() );
559             boolean isDefinedBySubclass = !thisClassProperties.contains( prop );
560             definedBySubclass.add( new Boolean JavaDoc(isDefinedBySubclass) );
561             propNullables.add( new Boolean JavaDoc( prop.isOptional() || isDefinedBySubclass) ); //TODO: is this completely correct?
562
types.add( prop.getType() );
563
564             Iterator JavaDoc colIter = prop.getColumnIterator();
565             String JavaDoc[] cols = new String JavaDoc[prop.getColumnSpan()];
566             String JavaDoc[] forms = new String JavaDoc[prop.getColumnSpan()];
567             int[] colnos = new int[prop.getColumnSpan()];
568             int[] formnos = new int[prop.getColumnSpan()];
569             int l = 0;
570             Boolean JavaDoc lazy = new Boolean JavaDoc( prop.isLazy() && lazyAvailable );
571             while ( colIter.hasNext() ) {
572                 Selectable thing = ( Selectable ) colIter.next();
573                 if ( thing.isFormula() ) {
574                     String JavaDoc template = thing.getTemplate( factory.getDialect() );
575                     formnos[l] = formulaTemplates.size();
576                     colnos[l] = -1;
577                     formulaTemplates.add( template );
578                     forms[l] = template;
579                     formulas.add( thing.getText( factory.getDialect() ) );
580                     formulaAliases.add( thing.getAlias( factory.getDialect() ) );
581                     formulasLazy.add( lazy );
582                 }
583                 else {
584                     String JavaDoc colName = thing.getTemplate( factory.getDialect() );
585                     colnos[l] = columns.size(); //before add :-)
586
formnos[l] = -1;
587                     columns.add( colName );
588                     cols[l] = colName;
589                     aliases.add( thing.getAlias( factory.getDialect(), prop.getValue().getTable() ) );
590                     columnsLazy.add( lazy );
591                     columnSelectables.add( new Boolean JavaDoc( prop.isSelectable() ) );
592                 }
593                 l++;
594             }
595             propColumns.add( cols );
596             templates.add( forms );
597             propColumnNumbers.add( colnos );
598             propFormulaNumbers.add( formnos );
599
600             joinedFetchesList.add( prop.getValue().getFetchMode() );
601         }
602         subclassColumnClosure = ArrayHelper.toStringArray( columns );
603         subclassColumnAliasClosure = ArrayHelper.toStringArray( aliases );
604         subclassColumnLazyClosure = ArrayHelper.toBooleanArray( columnsLazy );
605         subclassColumnSelectableClosure = ArrayHelper.toBooleanArray( columnSelectables );
606
607         subclassFormulaClosure = ArrayHelper.toStringArray( formulas );
608         subclassFormulaTemplateClosure = ArrayHelper.toStringArray( formulaTemplates );
609         subclassFormulaAliasClosure = ArrayHelper.toStringArray( formulaAliases );
610         subclassFormulaLazyClosure = ArrayHelper.toBooleanArray( formulasLazy );
611
612         subclassPropertyNameClosure = ArrayHelper.toStringArray( names );
613         subclassPropertySubclassNameClosure = ArrayHelper.toStringArray( classes );
614         subclassPropertyTypeClosure = ArrayHelper.toTypeArray( types );
615         subclassPropertyNullabilityClosure = ArrayHelper.toBooleanArray( propNullables );
616         subclassPropertyFormulaTemplateClosure = ArrayHelper.to2DStringArray( templates );
617         subclassPropertyColumnNameClosure = ArrayHelper.to2DStringArray( propColumns );
618         subclassPropertyColumnNumberClosure = ArrayHelper.to2DIntArray( propColumnNumbers );
619         subclassPropertyFormulaNumberClosure = ArrayHelper.to2DIntArray( propFormulaNumbers );
620
621         subclassPropertyFetchModeClosure = new FetchMode[joinedFetchesList.size()];
622         iter = joinedFetchesList.iterator();
623         int j = 0;
624         while ( iter.hasNext() ) subclassPropertyFetchModeClosure[j++] = ( FetchMode ) iter.next();
625
626         propertyDefinedOnSubclass = new boolean[definedBySubclass.size()];
627         iter = definedBySubclass.iterator();
628         j = 0;
629         while ( iter.hasNext() ) propertyDefinedOnSubclass[j++] = ( ( Boolean JavaDoc ) iter.next() ).booleanValue();
630
631         // Handle any filters applied to the class level
632
filterHelper = new FilterHelper( persistentClass.getFilterMap(), factory.getDialect() );
633
634         temporaryIdTableName = persistentClass.getTemporaryIdTableName();
635         temporaryIdTableDDL = persistentClass.getTemporaryIdTableDDL();
636     }
637
638     protected String JavaDoc generateLazySelectString() {
639
640         if ( !entityMetamodel.hasLazyProperties() ) return null;
641
642         HashSet JavaDoc tableNumbers = new HashSet JavaDoc();
643         ArrayList JavaDoc columnNumbers = new ArrayList JavaDoc();
644         ArrayList JavaDoc formulaNumbers = new ArrayList JavaDoc();
645         for ( int i = 0; i < lazyPropertyNames.length; i++ ) {
646             // all this only really needs to consider properties
647
// of this class, not its subclasses, but since we
648
// are reusing code used for sequential selects, we
649
// use the subclass closure
650
int propertyNumber = getSubclassPropertyIndex( lazyPropertyNames[i] );
651
652             int tableNumber = getSubclassPropertyTableNumber( propertyNumber );
653             tableNumbers.add( new Integer JavaDoc( tableNumber ) );
654
655             int[] colNumbers = subclassPropertyColumnNumberClosure[propertyNumber];
656             for ( int j = 0; j < colNumbers.length; j++ ) {
657                 if ( colNumbers[j]!=-1 ) {
658                     columnNumbers.add( new Integer JavaDoc( colNumbers[j] ) );
659                 }
660             }
661             int[] formNumbers = subclassPropertyFormulaNumberClosure[propertyNumber];
662             for ( int j = 0; j < formNumbers.length; j++ ) {
663                 if ( formNumbers[j]!=-1 ) {
664                     formulaNumbers.add( new Integer JavaDoc( formNumbers[j] ) );
665                 }
666             }
667         }
668         
669