1
//$Id: SingleTableEntityPersister.java 10040 2006-06-22 19:51:43Z steve.ebersole@jboss.com $
2
package org.hibernate.persister.entity;
4
import java.io.Serializable;
5
import java.util.ArrayList;
6
import java.util.HashMap;
7
import java.util.HashSet;
8
import java.util.Iterator;
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.engine.ExecuteUpdateResultCheckStyle;
18
import org.hibernate.mapping.Column;
19
import org.hibernate.mapping.Formula;
20
import org.hibernate.mapping.Join;
21
import org.hibernate.mapping.PersistentClass;
22
import org.hibernate.mapping.Property;
23
import org.hibernate.mapping.Selectable;
24
import org.hibernate.mapping.Subclass;
25
import org.hibernate.mapping.Table;
26
import org.hibernate.mapping.Value;
27
import org.hibernate.sql.InFragment;
28
import org.hibernate.sql.Insert;
29
import org.hibernate.sql.SelectFragment;
30
import org.hibernate.type.AssociationType;
31
import org.hibernate.type.DiscriminatorType;
32
import org.hibernate.type.Type;
33
import org.hibernate.util.ArrayHelper;
34
import org.hibernate.util.MarkerObject;
37
* The default implementation of the <tt>EntityPersister</tt> interface.
38
* Implements the "table-per-class-hierarchy" or "roll-up" mapping strategy
39
* for an entity class and its inheritence hierarchy. This is implemented
40
* as a single table holding all classes in the hierarchy with a discrimator
41
* column used to determine which concrete class is referenced.
45
public class SingleTableEntityPersister extends AbstractEntityPersister {
47
// the class hierarchy structure
48
private final int joinSpan;
49
private final String[] qualifiedTableNames;
50
private final boolean[] isInverseTable;
51
private final boolean[] isNullableTable;
52
private final String[][] keyColumnNames;
53
private final boolean[] cascadeDeleteEnabled;
54
private final boolean hasSequentialSelects;
56
private final String[] spaces;
58
private final String[] subclassClosure;
60
private final String[] subclassTableNameClosure;
61
private final boolean[] subclassTableIsLazyClosure;
62
private final boolean[] isInverseSubclassTable;
63
private final boolean[] isNullableSubclassTable;
64
private final boolean[] subclassTableSequentialSelect;
65
private final String[][] subclassTableKeyColumnClosure;
66
private final boolean[] isClassOrSuperclassTable;
68
// properties of this class, including inherited properties
69
private final int[] propertyTableNumbers;
71
// the closure of all columns used by the entire hierarchy including
72
// subclasses and superclasses of this class
73
private final int[] subclassPropertyTableNumberClosure;
75
private final int[] subclassColumnTableNumberClosure;
76
private final int[] subclassFormulaTableNumberClosure;
78
// discriminator column
79
private final Map subclassesByDiscriminatorValue = new HashMap();
80
private final boolean forceDiscriminator;
81
private final String discriminatorColumnName;
82
private final String discriminatorFormula;
83
private final String discriminatorFormulaTemplate;
84
private final String discriminatorAlias;
85
private final Type discriminatorType;
86
private final String discriminatorSQLValue;
87
private final boolean discriminatorInsertable;
89
private final String[] constraintOrderedTableNames;
90
private final String[][] constraintOrderedKeyColumnNames;
92
//private final Map propertyTableNumbersByName = new HashMap();
93
private final Map propertyTableNumbersByNameAndSubclass = new HashMap();
95
private final Map sequentialSelectStringsByEntityName = new HashMap();
97
private static final Object NULL_DISCRIMINATOR = new MarkerObject("<null discriminator>");
98
private static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject("<not null discriminator>");
102
public SingleTableEntityPersister(
103
final PersistentClass persistentClass,
104
final CacheConcurrencyStrategy cache,
105
final SessionFactoryImplementor factory,
106
final Mapping mapping)
107
throws HibernateException {
109
super(persistentClass, cache, factory);
113
joinSpan = persistentClass.getJoinClosureSpan()+1;
114
qualifiedTableNames = new String[joinSpan];
115
isInverseTable = new boolean[joinSpan];
116
isNullableTable = new boolean[joinSpan];
117
keyColumnNames = new String[joinSpan][];
118
final Table table = persistentClass.getRootTable();
119
qualifiedTableNames[0] = table.getQualifiedName(
120
factory.getDialect(),
121
factory.getSettings().getDefaultCatalogName(),
122
factory.getSettings().getDefaultSchemaName()
124
isInverseTable[0] = false;
125
isNullableTable[0] = false;
126
keyColumnNames[0] = getIdentifierColumnNames();
127
cascadeDeleteEnabled = new boolean[joinSpan];
130
customSQLInsert = new String[joinSpan];
131
customSQLUpdate = new String[joinSpan];
132
customSQLDelete = new String[joinSpan];
133
insertCallable = new boolean[joinSpan];
134
updateCallable = new boolean[joinSpan];
135
deleteCallable = new boolean[joinSpan];
136
insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];
137
updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];
138
deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];
140
customSQLInsert[0] = persistentClass.getCustomSQLInsert();
141
insertCallable[0] = customSQLInsert[0] != null && persistentClass.isCustomInsertCallable();
142
insertResultCheckStyles[0] = persistentClass.getCustomSQLInsertCheckStyle() == null
143
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLInsert[0], insertCallable[0] )
144
: persistentClass.getCustomSQLInsertCheckStyle();
145
customSQLUpdate[0] = persistentClass.getCustomSQLUpdate();
146
updateCallable[0] = customSQLUpdate[0] != null && persistentClass.isCustomUpdateCallable();
147
updateResultCheckStyles[0] = persistentClass.getCustomSQLUpdateCheckStyle() == null
148
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[0], updateCallable[0] )
149
: persistentClass.getCustomSQLUpdateCheckStyle();
150
customSQLDelete[0] = persistentClass.getCustomSQLDelete();
151
deleteCallable[0] = customSQLDelete[0] != null && persistentClass.isCustomDeleteCallable();
152
deleteResultCheckStyles[0] = persistentClass.getCustomSQLDeleteCheckStyle() == null
153
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[0], deleteCallable[0] )
154
: persistentClass.getCustomSQLDeleteCheckStyle();
158
Iterator joinIter = persistentClass.getJoinClosureIterator();
160
while ( joinIter.hasNext() ) {
161
Join join = (Join) joinIter.next();
162
qualifiedTableNames[j] = join.getTable().getQualifiedName(
163
factory.getDialect(),
164
factory.getSettings().getDefaultCatalogName(),
165
factory.getSettings().getDefaultSchemaName()
167
isInverseTable[j] = join.isInverse();
168
isNullableTable[j] = join.isOptional();
169
cascadeDeleteEnabled[j] = join.getKey().isCascadeDeleteEnabled() &&
170
factory.getDialect().supportsCascadeDelete();
172
customSQLInsert[j] = join.getCustomSQLInsert();
173
insertCallable[j] = customSQLInsert[j] != null && join.isCustomInsertCallable();
174
insertResultCheckStyles[j] = join.getCustomSQLInsertCheckStyle() == null
175
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLInsert[j], insertCallable[j] )
176
: join.getCustomSQLInsertCheckStyle();
177
customSQLUpdate[j] = join.getCustomSQLUpdate();
178
updateCallable[j] = customSQLUpdate[j] != null && join.isCustomUpdateCallable();
179
updateResultCheckStyles[j] = join.getCustomSQLUpdateCheckStyle() == null
180
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[j], updateCallable[j] )
181
: join.getCustomSQLUpdateCheckStyle();
182
customSQLDelete[j] = join.getCustomSQLDelete();
183
deleteCallable[j] = customSQLDelete[j] != null && join.isCustomDeleteCallable();
184
deleteResultCheckStyles[j] = join.getCustomSQLDeleteCheckStyle() == null
185
? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[j], deleteCallable[j] )
186
: join.getCustomSQLDeleteCheckStyle();
188
Iterator iter = join.getKey().getColumnIterator();
189
keyColumnNames[j] = new String[ join.getKey().getColumnSpan() ];
191
while ( iter.hasNext() ) {
192
Column col = (Column) iter.next();
193
keyColumnNames[j][i++] = col.getQuotedName( factory.getDialect() );
199
constraintOrderedTableNames = new String[qualifiedTableNames.length];
200
constraintOrderedKeyColumnNames = new String[qualifiedTableNames.length][];
201
for ( int i = qualifiedTableNames.length - 1, position = 0; i >= 0; i--, position++ ) {
202
constraintOrderedTableNames[position] = qualifiedTableNames[i];
203
constraintOrderedKeyColumnNames[position] = keyColumnNames[i];
206
spaces = ArrayHelper.join(
208
ArrayHelper.toStringArray( persistentClass.getSynchronizedTables() )
211
final boolean lazyAvailable = isInstrumented(EntityMode.POJO);
213
boolean hasDeferred = false;
214
ArrayList subclassTables = new ArrayList();
215
ArrayList joinKeyColumns = new ArrayList();
216
ArrayList isConcretes = new ArrayList();
217
ArrayList isDeferreds = new ArrayList();
218
ArrayList isInverses = new ArrayList();
219
ArrayList isNullables = new ArrayList();
220
ArrayList isLazies = new ArrayList();
221
subclassTables.add( qualifiedTableNames[0] );
222
joinKeyColumns.add( getIdentifierColumnNames() );
223
isConcretes.add(Boolean.TRUE);
224
isDeferreds.add(Boolean.FALSE);
225
isInverses.add(Boolean.FALSE);
226
isNullables.add(Boolean.FALSE);
227
isLazies.add(Boolean.FALSE);
228
joinIter = persistentClass.getSubclassJoinClosureIterator();
229
while ( joinIter.hasNext() ) {
230
Join join = (Join) joinIter.next();
231
isConcretes.add( new Boolean( persistentClass.isClassOrSuperclassJoin(join) ) );
232
isDeferreds.add( new Boolean( join.isSequentialSelect() ) );
233
isInverses.add( new Boolean( join.isInverse() ) );
234
isNullables.add( new Boolean( join.isOptional() ) );
235
isLazies.add( new Boolean( lazyAvailable && join.isLazy() ) );
236
if ( join.isSequentialSelect() && !persistentClass.isClassOrSuperclassJoin(join) ) hasDeferred = true;
237
subclassTables.add( join.getTable().getQualifiedName(
238
factory.getDialect(),
239
factory.getSettings().getDefaultCatalogName(),
240
factory.getSettings().getDefaultSchemaName()
242
Iterator iter = join.getKey().getColumnIterator();
243
String[] keyCols = new String[ join.getKey().getColumnSpan() ];
245
while ( iter.hasNext() ) {
246
Column col = (Column) iter.next();
247
keyCols[i++] = col.getQuotedName( factory.getDialect() );
249
joinKeyColumns.add(keyCols);
252
subclassTableSequentialSelect = ArrayHelper.toBooleanArray(isDeferreds);
253
subclassTableNameClosure = ArrayHelper.toStringArray(subclassTables);
254
subclassTableIsLazyClosure = ArrayHelper.toBooleanArray(isLazies);
255
subclassTableKeyColumnClosure = ArrayHelper.to2DStringArray(joinKeyColumns);
256
isClassOrSuperclassTable = ArrayHelper.toBooleanArray(isConcretes);
257
isInverseSubclassTable = ArrayHelper.toBooleanArray(isInverses);
258
isNullableSubclassTable = ArrayHelper.toBooleanArray(isNullables);
259
hasSequentialSelects = hasDeferred;
263
final Object discriminatorValue;
264
if ( persistentClass.isPolymorphic() ) {
265
Value discrimValue = persistentClass.getDiscriminator();
266
if (discrimValue==null) {
267
throw new MappingException("discriminator mapping required for single table polymorphic persistence");
269
forceDiscriminator = persistentClass.isForceDiscriminator();
270
Selectable selectable = (Selectable) discrimValue.getColumnIterator().next();
271
if ( discrimValue.hasFormula() ) {
272
Formula formula = (Formula) selectable;
273
discriminatorFormula = formula.getFormula();
274
discriminatorFormulaTemplate = formula.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() );
275
discriminatorColumnName = null;
276
discriminatorAlias = "clazz_";
279
Column column = (Column) selectable;
280
discriminatorColumnName = column.getQuotedName( factory.getDialect() );
281
discriminatorAlias = column.getAlias( factory.getDialect(), persistentClass.getRootTable() );
282
discriminatorFormula = null;
283
discriminatorFormulaTemplate = null;
285
discriminatorType = persistentClass.getDiscriminator().getType();
286
if ( persistentClass.isDiscriminatorValueNull() ) {
287
discriminatorValue = NULL_DISCRIMINATOR;
288
discriminatorSQLValue = InFragment.NULL;
289
discriminatorInsertable = false;
291
else if ( persistentClass.isDiscriminatorValueNotNull() ) {
292
discriminatorValue = NOT_NULL_DISCRIMINATOR;
293
discriminatorSQLValue = InFragment.NOT_NULL;
294
discriminatorInsertable = false;
297
discriminatorInsertable = persistentClass.isDiscriminatorInsertable() && !discrimValue.hasFormula();
299
DiscriminatorType dtype = (DiscriminatorType) discriminatorType;
300
discriminatorValue = dtype.stringToObject( persistentClass.getDiscriminatorValue() );
301
discriminatorSQLValue = dtype.objectToSQLString( discriminatorValue, factory.getDialect() );
303
catch (ClassCastException cce) {
304
throw new MappingException("Illegal discriminator type: " + discriminatorType.getName() );
306
catch (Exception e) {
307
throw new MappingException("Could not format discriminator value to SQL string", e);
312
forceDiscriminator = false;
313
discriminatorInsertable = false;
314
discriminatorColumnName = null;
315
discriminatorAlias = null;
316
discriminatorType = null;
317
discriminatorValue = null;
318
discriminatorSQLValue = null;
319
discriminatorFormula = null;
320
discriminatorFormulaTemplate = null;
325
propertyTableNumbers = new int[ getPropertySpan() ];
326
Iterator iter = persistentClass.getPropertyClosureIterator();
328
while( iter.hasNext() ) {
329
Property prop = (Property) iter.next();
330
propertyTableNumbers[i++] = persistentClass.getJoinNumber(prop);
334
//TODO: code duplication with JoinedSubclassEntityPersister
336
ArrayList columnJoinNumbers = new ArrayList();
337
ArrayList formulaJoinedNumbers = new ArrayList();
338
ArrayList propertyJoinNumbers = new ArrayList();
340
iter = persistentClass.getSubclassPropertyClosureIterator();
341
while ( iter.hasNext() ) {
342
Property prop = (Property) iter.next();
343
Integer join = new Integer( persistentClass.getJoinNumber(prop) );
344
propertyJoinNumbers.add(join);
346
//propertyTableNumbersByName.put( prop.getName(), join );
347
propertyTableNumbersByNameAndSubclass.put(
348
prop.getPersistentClass().getEntityName() + '.' + prop.getName(),
352
Iterator citer = prop.getColumnIterator();
353
while ( citer.hasNext() ) {
354
Selectable thing = (Selectable) citer.next();
355
if ( thing.isFormula() ) {
356
formulaJoinedNumbers.add(join);
359
columnJoinNumbers.add(join);
363
subclassColumnTableNumberClosure = ArrayHelper.toIntArray(columnJoinNumbers);
364
subclassFormulaTableNumberClosure = ArrayHelper.toIntArray(formulaJoinedNumbers);
365
subclassPropertyTableNumberClosure = ArrayHelper.toIntArray(propertyJoinNumbers);
367
int subclassSpan = persistentClass.getSubclassSpan() + 1;
368
subclassClosure = new String[subclassSpan];
369
subclassClosure[0] = getEntityName();
370
if ( persistentClass.isPolymorphic() ) {
371
subclassesByDiscriminatorValue.put( discriminatorValue, getEntityName() );
375
if ( persistentClass.isPolymorphic() ) {
376
iter = persistentClass.getSubclassIterator();
378
while ( iter.hasNext() ) {
379
Subclass sc = (Subclass) iter.next();
380
subclassClosure[k++] = sc.getEntityName();
381
if ( sc.isDiscriminatorValueNull() ) {
382
subclassesByDiscriminatorValue.put( NULL_DISCRIMINATOR, sc.getEntityName() );
384
else if ( sc.isDiscriminatorValueNotNull() ) {
385
subclassesByDiscriminatorValue.put( NOT_NULL_DISCRIMINATOR, sc.getEntityName() );
389
DiscriminatorType dtype = (DiscriminatorType) discriminatorType;
390
subclassesByDiscriminatorValue.put(
391
dtype.stringToObject( sc.getDiscriminatorValue() ),
395
catch (ClassCastException cce) {
396
throw new MappingException("Illegal discriminator type: " + discriminatorType.getName() );
398
catch (Exception e) {
399
throw new MappingException("Error parsing discriminator value", e);
407
initSubclassPropertyAliasesMap(persistentClass);
409
postConstruct(mapping);
413
protected boolean isInverseTable(int j) {
414
return isInverseTable[j];
417
protected boolean isInverseSubclassTable(int j) {
418
return isInverseSubclassTable[j];
421
public String getDiscriminatorColumnName() {
422
return discriminatorColumnName;
425
protected String getDiscriminatorAlias() {
426
return discriminatorAlias;
429
protected String getDiscriminatorFormulaTemplate() {
430
return discriminatorFormulaTemplate;
433
public String getTableName() {
434
return qualifiedTableNames[0];
437
public Type getDiscriminatorType() {
438
return discriminatorType;
441
public String getDiscriminatorSQLValue() {
442
return discriminatorSQLValue;
445
public String[] getSubclassClosure() {
446
return subclassClosure;
449
public String getSubclassForDiscriminatorValue(Object value) {
451
return (String) subclassesByDiscriminatorValue.get(NULL_DISCRIMINATOR);
454
String result = (String) subclassesByDiscriminatorValue.get(value);
455
if (result==null) result = (String) subclassesByDiscriminatorValue.get(NOT_NULL_DISCRIMINATOR);
460
public Serializable[] getPropertySpaces() {
466
protected boolean isDiscriminatorFormula() {
467
return discriminatorColumnName==null;
470
protected String getDiscriminatorFormula() {
471
return discriminatorFormula;
474
protected String getTableName(int j) {
475
return qualifiedTableNames[j];
478
protected String[] getKeyColumns(int j) {
479
return keyColumnNames[j];
482
protected boolean isTableCascadeDeleteEnabled(int j) {
483
return cascadeDeleteEnabled[j];
486
protected boolean isPropertyOfTable(int property, int j) {
487
return propertyTableNumbers[property]==j;
490
protected boolean isSubclassTableSequentialSelect(int j) {
491
return subclassTableSequentialSelect[j] && !isClassOrSuperclassTable[j];
496
public String fromTableFragment(String name) {
497
return getTableName() + ' ' + name;
500
public String filterFragment(String alias) throws MappingException {
501
String result = discriminatorFilterFragment(alias);
502
if ( hasWhere() ) result += " and " + getSQLWhereString(alias);
506
public String oneToManyFilterFragment(String alias) throws MappingException {
507
return forceDiscriminator ?
508
discriminatorFilterFragment(alias) :
512
private String discriminatorFilterFragment(String alias) throws MappingException {
513
if ( needsDiscriminator() ) {
514
InFragment frag = new InFragment();
516
if ( isDiscriminatorFormula() ) {
517
frag.setFormula( alias, getDiscriminatorFormulaTemplate() );
520
frag.setColumn( alias, getDiscriminatorColumnName() );
523
String[] subclasses = getSubclassClosure();
524
for ( int i=0; i<subclasses.length; i++ ) {
525
final Queryable queryable = (Queryable) getFactory().getEntityPersister( subclasses[i] );
526
if ( !queryable.isAbstract() ) frag.addValue( queryable.getDiscriminatorSQLValue() );
529
StringBuffer buf = new StringBuffer(50)
531
.append( frag.toFragmentString() );
533
return buf.toString();
540
private boolean needsDiscriminator() {
541
return forceDiscriminator || isInherited();
544
public String getSubclassPropertyTableName(int i) {
545
return subclassTableNameClosure[ subclassPropertyTableNumberClosure[i] ];
548
protected void addDiscriminatorToSelect(SelectFragment select, String name, String suffix) {
549
if ( isDiscriminatorFormula() ) {
550
select.addFormula( name, getDiscriminatorFormulaTemplate(), getDiscriminatorAlias() );
553
select.addColumn( name, getDiscriminatorColumnName(), getDiscriminatorAlias() );
557
protected int[] getPropertyTableNumbersInSelect() {
558
return propertyTableNumbers;
561
protected int getSubclassPropertyTableNumber(int i) {
562
return subclassPropertyTableNumberClosure[i];
565
public int getTableSpan() {
569
protected void addDiscriminatorToInsert(Insert insert) {
571
if (discriminatorInsertable) {
572
insert.addColumn( getDiscriminatorColumnName(), discriminatorSQLValue );
577
protected int[] getSubclassColumnTableNumberClosure() {
578
return subclassColumnTableNumberClosure;
581
protected int[] getSubclassFormulaTableNumberClosure() {
582
return subclassFormulaTableNumberClosure;
585
protected int[] getPropertyTableNumbers() {
586
return propertyTableNumbers;
589
protected boolean isSubclassPropertyDeferred(String propertyName, String entityName) {
590
return hasSequentialSelects &&
591
isSubclassTableSequentialSelect( getSubclassPropertyTableNumber(propertyName, entityName) );
594
public boolean hasSequentialSelect() {
595
return hasSequentialSelects;
598
private int getSubclassPropertyTableNumber(String propertyName, String entityName) {
599
Type type = propertyMapping.toType(propertyName);
600
if ( type.isAssociationType() && ( (AssociationType) type ).useLHSPrimaryKey() ) return 0;
601
final Integer tabnum = (Integer) propertyTableNumbersByNameAndSubclass.get(entityName + '.' + propertyName);
602
return tabnum==null ? 0 : tabnum.intValue();
605
protected String getSequentialSelect(String entityName) {
606
return (String) sequentialSelectStringsByEntityName.get(entityName);
609
private String generateSequentialSelect(Loadable persister) {
610
//if ( this==persister || !hasSequentialSelects ) return null;
612
//note that this method could easily be moved up to BasicEntityPersister,
613
//if we ever needed to reuse it from other subclasses
615
//figure out which tables need to be fetched
616
AbstractEntityPersister subclassPersister = (AbstractEntityPersister) persister;
617
HashSet tableNumbers = new HashSet();
618
String[] props = subclassPersister.getPropertyNames();
619
String[] classes = subclassPersister.getPropertySubclassNames();
620
for ( int i=0; i<props.length; i++ ) {
621
int propTableNumber = getSubclassPropertyTableNumber( props[i], classes[i] );
622
if ( isSubclassTableSequentialSelect(propTableNumber) && !isSubclassTableLazy(propTableNumber) ) {
623
tableNumbers.add( new Integer(propTableNumber) );
626
if ( tableNumbers.isEmpty() ) return null;
628
//figure out which columns are needed
629
ArrayList columnNumbers = new ArrayList();
630
final int[] columnTableNumbers = getSubclassColumnTableNumberClosure();
631
for ( int i=0; i<getSubclassColumnClosure().length; i++ ) {
632
if ( tableNumbers.contains( new Integer( columnTableNumbers[i] ) ) ) {
633
columnNumbers.add( new Integer(i) );
637
//figure out which formulas are needed
638
ArrayList formulaNumbers = new ArrayList();
639
final int[] formulaTableNumbers = getSubclassColumnTableNumberClosure();
640
for ( int i=0; i<getSubclassFormulaTemplateClosure().length; i++ ) {
641
if ( tableNumbers.contains( new Integer( formulaTableNumbers[i] ) ) ) {
642
formulaNumbers.add( new Integer(i) );
648
ArrayHelper.toIntArray(tableNumbers),
649
ArrayHelper.toIntArray(columnNumbers),
650
ArrayHelper.toIntArray(formulaNumbers)
655
protected String[] getSubclassTableKeyColumns(int j) {
656
return subclassTableKeyColumnClosure[j];
659
public String getSubclassTableName(int j) {
660
return subclassTableNameClosure[j];
663
public int getSubclassTableSpan() {
664
return subclassTableNameClosure.length;
667
protected boolean isClassOrSuperclassTable(int j) {
668
return isClassOrSuperclassTable[j];
671
protected boolean isSubclassTableLazy(int j) {
672
return subclassTableIsLazyClosure[j];
675
protected boolean isNullableTable(int j) {
676
return isNullableTable[j];
679
protected boolean isNullableSubclassTable(int j) {
680
return isNullableSubclassTable[j];
683
public String getPropertyTableName(String propertyName) {
684
Integer index = getEntityMetamodel().getPropertyIndexOrNull(propertyName);
685
if (index==null) return null;
686
return qualifiedTableNames[ propertyTableNumbers[ index.intValue() ] ];
689
public void postInstantiate() {
690
super.postInstantiate();
691
if (hasSequentialSelects) {
692
String[] entityNames = getSubclassClosure();
693
for ( int i=1; i<entityNames.length; i++ ) {
694
Loadable loadable = (Loadable) getFactory().getEntityPersister( entityNames[i] );
695
if ( !loadable.isAbstract() ) { //perhaps not really necessary...
696
String sequentialSelect = generateSequentialSelect(loadable);
697
sequentialSelectStringsByEntityName.put( entityNames[i], sequentialSelect );
703
public boolean isMultiTable() {
704
return getTableSpan() > 1;
707
public String[] getConstraintOrderedTableNameClosure() {
708
return constraintOrderedTableNames;
711
public String[][] getContraintOrderedTableKeyColumnClosure() {
712
return constraintOrderedKeyColumnNames;