FileDocCategorySizeDatePackage
SingleTableEntityPersister.javaAPI DocHibernate 3.2.525389Thu Jun 22 14:51:44 BST 2006org.hibernate.persister.entity

SingleTableEntityPersister

public class SingleTableEntityPersister extends AbstractEntityPersister
The default implementation of the EntityPersister interface. Implements the "table-per-class-hierarchy" or "roll-up" mapping strategy for an entity class and its inheritence hierarchy. This is implemented as a single table holding all classes in the hierarchy with a discrimator column used to determine which concrete class is referenced.
author
Gavin King

Fields Summary
private final int
joinSpan
private final String[]
qualifiedTableNames
private final boolean[]
isInverseTable
private final boolean[]
isNullableTable
private final String[]
keyColumnNames
private final boolean[]
cascadeDeleteEnabled
private final boolean
hasSequentialSelects
private final String[]
spaces
private final String[]
subclassClosure
private final String[]
subclassTableNameClosure
private final boolean[]
subclassTableIsLazyClosure
private final boolean[]
isInverseSubclassTable
private final boolean[]
isNullableSubclassTable
private final boolean[]
subclassTableSequentialSelect
private final String[]
subclassTableKeyColumnClosure
private final boolean[]
isClassOrSuperclassTable
private final int[]
propertyTableNumbers
private final int[]
subclassPropertyTableNumberClosure
private final int[]
subclassColumnTableNumberClosure
private final int[]
subclassFormulaTableNumberClosure
private final Map
subclassesByDiscriminatorValue
private final boolean
forceDiscriminator
private final String
discriminatorColumnName
private final String
discriminatorFormula
private final String
discriminatorFormulaTemplate
private final String
discriminatorAlias
private final org.hibernate.type.Type
discriminatorType
private final String
discriminatorSQLValue
private final boolean
discriminatorInsertable
private final String[]
constraintOrderedTableNames
private final String[]
constraintOrderedKeyColumnNames
private final Map
propertyTableNumbersByNameAndSubclass
private final Map
sequentialSelectStringsByEntityName
private static final Object
NULL_DISCRIMINATOR
private static final Object
NOT_NULL_DISCRIMINATOR
Constructors Summary
public SingleTableEntityPersister(org.hibernate.mapping.PersistentClass persistentClass, org.hibernate.cache.CacheConcurrencyStrategy cache, org.hibernate.engine.SessionFactoryImplementor factory, org.hibernate.engine.Mapping mapping)


	//INITIALIZATION:

	 
			   
			  
			  
			  
	  

		super(persistentClass, cache, factory);

		// CLASS + TABLE

		joinSpan = persistentClass.getJoinClosureSpan()+1;
		qualifiedTableNames = new String[joinSpan];
		isInverseTable = new boolean[joinSpan];
		isNullableTable = new boolean[joinSpan];
		keyColumnNames = new String[joinSpan][];
		final Table table = persistentClass.getRootTable();
		qualifiedTableNames[0] = table.getQualifiedName( 
				factory.getDialect(), 
				factory.getSettings().getDefaultCatalogName(), 
				factory.getSettings().getDefaultSchemaName() 
		);
		isInverseTable[0] = false;
		isNullableTable[0] = false;
		keyColumnNames[0] = getIdentifierColumnNames();
		cascadeDeleteEnabled = new boolean[joinSpan];

		// Custom sql
		customSQLInsert = new String[joinSpan];
		customSQLUpdate = new String[joinSpan];
		customSQLDelete = new String[joinSpan];
		insertCallable = new boolean[joinSpan];
		updateCallable = new boolean[joinSpan];
		deleteCallable = new boolean[joinSpan];
		insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];
		updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];
		deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];

		customSQLInsert[0] = persistentClass.getCustomSQLInsert();
		insertCallable[0] = customSQLInsert[0] != null && persistentClass.isCustomInsertCallable();
		insertResultCheckStyles[0] = persistentClass.getCustomSQLInsertCheckStyle() == null
									  ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLInsert[0], insertCallable[0] )
									  : persistentClass.getCustomSQLInsertCheckStyle();
		customSQLUpdate[0] = persistentClass.getCustomSQLUpdate();
		updateCallable[0] = customSQLUpdate[0] != null && persistentClass.isCustomUpdateCallable();
		updateResultCheckStyles[0] = persistentClass.getCustomSQLUpdateCheckStyle() == null
									  ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[0], updateCallable[0] )
									  : persistentClass.getCustomSQLUpdateCheckStyle();
		customSQLDelete[0] = persistentClass.getCustomSQLDelete();
		deleteCallable[0] = customSQLDelete[0] != null && persistentClass.isCustomDeleteCallable();
		deleteResultCheckStyles[0] = persistentClass.getCustomSQLDeleteCheckStyle() == null
									  ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[0], deleteCallable[0] )
									  : persistentClass.getCustomSQLDeleteCheckStyle();

		// JOINS

		Iterator joinIter = persistentClass.getJoinClosureIterator();
		int j = 1;
		while ( joinIter.hasNext() ) {
			Join join = (Join) joinIter.next();
			qualifiedTableNames[j] = join.getTable().getQualifiedName( 
					factory.getDialect(), 
					factory.getSettings().getDefaultCatalogName(), 
					factory.getSettings().getDefaultSchemaName() 
			);
			isInverseTable[j] = join.isInverse();
			isNullableTable[j] = join.isOptional();
			cascadeDeleteEnabled[j] = join.getKey().isCascadeDeleteEnabled() && 
				factory.getDialect().supportsCascadeDelete();

			customSQLInsert[j] = join.getCustomSQLInsert();
			insertCallable[j] = customSQLInsert[j] != null && join.isCustomInsertCallable();
			insertResultCheckStyles[j] = join.getCustomSQLInsertCheckStyle() == null
			                              ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLInsert[j], insertCallable[j] )
		                                  : join.getCustomSQLInsertCheckStyle();
			customSQLUpdate[j] = join.getCustomSQLUpdate();
			updateCallable[j] = customSQLUpdate[j] != null && join.isCustomUpdateCallable();
			updateResultCheckStyles[j] = join.getCustomSQLUpdateCheckStyle() == null
			                              ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[j], updateCallable[j] )
		                                  : join.getCustomSQLUpdateCheckStyle();
			customSQLDelete[j] = join.getCustomSQLDelete();
			deleteCallable[j] = customSQLDelete[j] != null && join.isCustomDeleteCallable();
			deleteResultCheckStyles[j] = join.getCustomSQLDeleteCheckStyle() == null
			                              ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[j], deleteCallable[j] )
		                                  : join.getCustomSQLDeleteCheckStyle();

			Iterator iter = join.getKey().getColumnIterator();
			keyColumnNames[j] = new String[ join.getKey().getColumnSpan() ];
			int i = 0;
			while ( iter.hasNext() ) {
				Column col = (Column) iter.next();
				keyColumnNames[j][i++] = col.getQuotedName( factory.getDialect() );
			}

			j++;
		}

		constraintOrderedTableNames = new String[qualifiedTableNames.length];
		constraintOrderedKeyColumnNames = new String[qualifiedTableNames.length][];
		for ( int i = qualifiedTableNames.length - 1, position = 0; i >= 0; i--, position++ ) {
			constraintOrderedTableNames[position] = qualifiedTableNames[i];
			constraintOrderedKeyColumnNames[position] = keyColumnNames[i];
		}

		spaces = ArrayHelper.join(
				qualifiedTableNames, 
				ArrayHelper.toStringArray( persistentClass.getSynchronizedTables() )
		);
		
		final boolean lazyAvailable = isInstrumented(EntityMode.POJO);

		boolean hasDeferred = false;
		ArrayList subclassTables = new ArrayList();
		ArrayList joinKeyColumns = new ArrayList();
		ArrayList isConcretes = new ArrayList();
		ArrayList isDeferreds = new ArrayList();
		ArrayList isInverses = new ArrayList();
		ArrayList isNullables = new ArrayList();
		ArrayList isLazies = new ArrayList();
		subclassTables.add( qualifiedTableNames[0] );
		joinKeyColumns.add( getIdentifierColumnNames() );
		isConcretes.add(Boolean.TRUE);
		isDeferreds.add(Boolean.FALSE);
		isInverses.add(Boolean.FALSE);
		isNullables.add(Boolean.FALSE);
		isLazies.add(Boolean.FALSE);
		joinIter = persistentClass.getSubclassJoinClosureIterator();
		while ( joinIter.hasNext() ) {
			Join join = (Join) joinIter.next();
			isConcretes.add( new Boolean( persistentClass.isClassOrSuperclassJoin(join) ) );
			isDeferreds.add( new Boolean( join.isSequentialSelect() ) );
			isInverses.add( new Boolean( join.isInverse() ) );
			isNullables.add( new Boolean( join.isOptional() ) );
			isLazies.add( new Boolean( lazyAvailable && join.isLazy() ) );
			if ( join.isSequentialSelect() && !persistentClass.isClassOrSuperclassJoin(join) ) hasDeferred = true;
			subclassTables.add( join.getTable().getQualifiedName( 
					factory.getDialect(), 
					factory.getSettings().getDefaultCatalogName(), 
					factory.getSettings().getDefaultSchemaName() 
			) );
			Iterator iter = join.getKey().getColumnIterator();
			String[] keyCols = new String[ join.getKey().getColumnSpan() ];
			int i = 0;
			while ( iter.hasNext() ) {
				Column col = (Column) iter.next();
				keyCols[i++] = col.getQuotedName( factory.getDialect() );
			}
			joinKeyColumns.add(keyCols);
		}
		
		subclassTableSequentialSelect = ArrayHelper.toBooleanArray(isDeferreds);
		subclassTableNameClosure = ArrayHelper.toStringArray(subclassTables);
		subclassTableIsLazyClosure = ArrayHelper.toBooleanArray(isLazies);
		subclassTableKeyColumnClosure = ArrayHelper.to2DStringArray(joinKeyColumns);
		isClassOrSuperclassTable = ArrayHelper.toBooleanArray(isConcretes);
		isInverseSubclassTable = ArrayHelper.toBooleanArray(isInverses);
		isNullableSubclassTable = ArrayHelper.toBooleanArray(isNullables);
		hasSequentialSelects = hasDeferred;

		// DISCRIMINATOR

		final Object discriminatorValue;
		if ( persistentClass.isPolymorphic() ) {
			Value discrimValue = persistentClass.getDiscriminator();
			if (discrimValue==null) {
				throw new MappingException("discriminator mapping required for single table polymorphic persistence");
			}
			forceDiscriminator = persistentClass.isForceDiscriminator();
			Selectable selectable = (Selectable) discrimValue.getColumnIterator().next();
			if ( discrimValue.hasFormula() ) {
				Formula formula = (Formula) selectable;
				discriminatorFormula = formula.getFormula();
				discriminatorFormulaTemplate = formula.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() );
				discriminatorColumnName = null;
				discriminatorAlias = "clazz_";
			}
			else {
				Column column = (Column) selectable;
				discriminatorColumnName = column.getQuotedName( factory.getDialect() );
				discriminatorAlias = column.getAlias( factory.getDialect(), persistentClass.getRootTable() );
				discriminatorFormula = null;
				discriminatorFormulaTemplate = null;
			}
			discriminatorType = persistentClass.getDiscriminator().getType();
			if ( persistentClass.isDiscriminatorValueNull() ) {
				discriminatorValue = NULL_DISCRIMINATOR;
				discriminatorSQLValue = InFragment.NULL;
				discriminatorInsertable = false;
			}
			else if ( persistentClass.isDiscriminatorValueNotNull() ) {
				discriminatorValue = NOT_NULL_DISCRIMINATOR;
				discriminatorSQLValue = InFragment.NOT_NULL;
				discriminatorInsertable = false;
			}
			else {
				discriminatorInsertable = persistentClass.isDiscriminatorInsertable() && !discrimValue.hasFormula();
				try {
					DiscriminatorType dtype = (DiscriminatorType) discriminatorType;
					discriminatorValue = dtype.stringToObject( persistentClass.getDiscriminatorValue() );
					discriminatorSQLValue = dtype.objectToSQLString( discriminatorValue, factory.getDialect() );
				}
				catch (ClassCastException cce) {
					throw new MappingException("Illegal discriminator type: " + discriminatorType.getName() );
				}
				catch (Exception e) {
					throw new MappingException("Could not format discriminator value to SQL string", e);
				}
			}
		}
		else {
			forceDiscriminator = false;
			discriminatorInsertable = false;
			discriminatorColumnName = null;
			discriminatorAlias = null;
			discriminatorType = null;
			discriminatorValue = null;
			discriminatorSQLValue = null;
			discriminatorFormula = null;
			discriminatorFormulaTemplate = null;
		}

		// PROPERTIES

		propertyTableNumbers = new int[ getPropertySpan() ];
		Iterator iter = persistentClass.getPropertyClosureIterator();
		int i=0;
		while( iter.hasNext() ) {
			Property prop = (Property) iter.next();
			propertyTableNumbers[i++] = persistentClass.getJoinNumber(prop);

		}

		//TODO: code duplication with JoinedSubclassEntityPersister
		
		ArrayList columnJoinNumbers = new ArrayList();
		ArrayList formulaJoinedNumbers = new ArrayList();
		ArrayList propertyJoinNumbers = new ArrayList();
		
		iter = persistentClass.getSubclassPropertyClosureIterator();
		while ( iter.hasNext() ) {
			Property prop = (Property) iter.next();
			Integer join = new Integer( persistentClass.getJoinNumber(prop) );
			propertyJoinNumbers.add(join);

			//propertyTableNumbersByName.put( prop.getName(), join );
			propertyTableNumbersByNameAndSubclass.put( 
					prop.getPersistentClass().getEntityName() + '." + prop.getName(), 
					join 
			);

			Iterator citer = prop.getColumnIterator();
			while ( citer.hasNext() ) {
				Selectable thing = (Selectable) citer.next();
				if ( thing.isFormula() ) {
					formulaJoinedNumbers.add(join);
				}
				else {
					columnJoinNumbers.add(join);
				}
			}
		}
		subclassColumnTableNumberClosure = ArrayHelper.toIntArray(columnJoinNumbers);
		subclassFormulaTableNumberClosure = ArrayHelper.toIntArray(formulaJoinedNumbers);
		subclassPropertyTableNumberClosure = ArrayHelper.toIntArray(propertyJoinNumbers);

		int subclassSpan = persistentClass.getSubclassSpan() + 1;
		subclassClosure = new String[subclassSpan];
		subclassClosure[0] = getEntityName();
		if ( persistentClass.isPolymorphic() ) {
			subclassesByDiscriminatorValue.put( discriminatorValue, getEntityName() );
		}

		// SUBCLASSES
		if ( persistentClass.isPolymorphic() ) {
			iter = persistentClass.getSubclassIterator();
			int k=1;
			while ( iter.hasNext() ) {
				Subclass sc = (Subclass) iter.next();
				subclassClosure[k++] = sc.getEntityName();
				if ( sc.isDiscriminatorValueNull() ) {
					subclassesByDiscriminatorValue.put( NULL_DISCRIMINATOR, sc.getEntityName() );
				}
				else if ( sc.isDiscriminatorValueNotNull() ) {
					subclassesByDiscriminatorValue.put( NOT_NULL_DISCRIMINATOR, sc.getEntityName() );
				}
				else {
					try {
						DiscriminatorType dtype = (DiscriminatorType) discriminatorType;
						subclassesByDiscriminatorValue.put(
							dtype.stringToObject( sc.getDiscriminatorValue() ),
							sc.getEntityName()
						);
					}
					catch (ClassCastException cce) {
						throw new MappingException("Illegal discriminator type: " + discriminatorType.getName() );
					}
					catch (Exception e) {
						throw new MappingException("Error parsing discriminator value", e);
					}
				}
			}
		}

		initLockers();

		initSubclassPropertyAliasesMap(persistentClass);
		
		postConstruct(mapping);

	
Methods Summary
protected voidaddDiscriminatorToInsert(org.hibernate.sql.Insert insert)


		if (discriminatorInsertable) {
			insert.addColumn( getDiscriminatorColumnName(), discriminatorSQLValue );
		}

	
protected voidaddDiscriminatorToSelect(org.hibernate.sql.SelectFragment select, java.lang.String name, java.lang.String suffix)

		if ( isDiscriminatorFormula() ) {
			select.addFormula( name, getDiscriminatorFormulaTemplate(), getDiscriminatorAlias() );
		}
		else {
			select.addColumn( name, getDiscriminatorColumnName(),  getDiscriminatorAlias() );
		}
	
private java.lang.StringdiscriminatorFilterFragment(java.lang.String alias)

		if ( needsDiscriminator() ) {
			InFragment frag = new InFragment();

			if ( isDiscriminatorFormula() ) {
				frag.setFormula( alias, getDiscriminatorFormulaTemplate() );
			}
			else {
				frag.setColumn( alias, getDiscriminatorColumnName() );
			}

			String[] subclasses = getSubclassClosure();
			for ( int i=0; i<subclasses.length; i++ ) {
				final Queryable queryable = (Queryable) getFactory().getEntityPersister( subclasses[i] );
				if ( !queryable.isAbstract() ) frag.addValue( queryable.getDiscriminatorSQLValue() );
			}

			StringBuffer buf = new StringBuffer(50)
				.append(" and ")
				.append( frag.toFragmentString() );

			return buf.toString();
		}
		else {
			return "";
		}
	
public java.lang.StringfilterFragment(java.lang.String alias)

		String result = discriminatorFilterFragment(alias);
		if ( hasWhere() ) result += " and " + getSQLWhereString(alias);
		return result;
	
public java.lang.StringfromTableFragment(java.lang.String name)

		return getTableName() + ' " + name;
	
private java.lang.StringgenerateSequentialSelect(Loadable persister)

		//if ( this==persister || !hasSequentialSelects ) return null;

		//note that this method could easily be moved up to BasicEntityPersister,
		//if we ever needed to reuse it from other subclasses
		
		//figure out which tables need to be fetched
		AbstractEntityPersister subclassPersister = (AbstractEntityPersister) persister;
		HashSet tableNumbers = new HashSet();
		String[] props = subclassPersister.getPropertyNames();
		String[] classes = subclassPersister.getPropertySubclassNames();
		for ( int i=0; i<props.length; i++ ) {
			int propTableNumber = getSubclassPropertyTableNumber( props[i], classes[i] );
			if ( isSubclassTableSequentialSelect(propTableNumber) && !isSubclassTableLazy(propTableNumber) ) {
				tableNumbers.add( new Integer(propTableNumber) );
			}
		}
		if ( tableNumbers.isEmpty() ) return null;
		
		//figure out which columns are needed
		ArrayList columnNumbers = new ArrayList();
		final int[] columnTableNumbers = getSubclassColumnTableNumberClosure();
		for ( int i=0; i<getSubclassColumnClosure().length; i++ ) {
			if ( tableNumbers.contains( new Integer( columnTableNumbers[i] ) ) ) {
				columnNumbers.add( new Integer(i) );
			}
		}
		
		//figure out which formulas are needed
		ArrayList formulaNumbers = new ArrayList();
		final int[] formulaTableNumbers = getSubclassColumnTableNumberClosure();
		for ( int i=0; i<getSubclassFormulaTemplateClosure().length; i++ ) {
			if ( tableNumbers.contains( new Integer( formulaTableNumbers[i] ) ) ) {
				formulaNumbers.add( new Integer(i) );
			}
		}
		
		//render the SQL
		return renderSelect( 
			ArrayHelper.toIntArray(tableNumbers),
			ArrayHelper.toIntArray(columnNumbers),
			ArrayHelper.toIntArray(formulaNumbers)
		);
	
public java.lang.String[]getConstraintOrderedTableNameClosure()

		return constraintOrderedTableNames;
	
public java.lang.String[][]getContraintOrderedTableKeyColumnClosure()

		return constraintOrderedKeyColumnNames;
	
protected java.lang.StringgetDiscriminatorAlias()

		return discriminatorAlias;
	
public java.lang.StringgetDiscriminatorColumnName()

		return discriminatorColumnName;
	
protected java.lang.StringgetDiscriminatorFormula()

		return discriminatorFormula;
	
protected java.lang.StringgetDiscriminatorFormulaTemplate()

		return discriminatorFormulaTemplate;
	
public java.lang.StringgetDiscriminatorSQLValue()

		return discriminatorSQLValue;
	
public org.hibernate.type.TypegetDiscriminatorType()

		return discriminatorType;
	
protected java.lang.String[]getKeyColumns(int j)

		return keyColumnNames[j];
	
public java.io.Serializable[]getPropertySpaces()

		return spaces;
	
public java.lang.StringgetPropertyTableName(java.lang.String propertyName)

		Integer index = getEntityMetamodel().getPropertyIndexOrNull(propertyName);
		if (index==null) return null;
		return qualifiedTableNames[ propertyTableNumbers[ index.intValue() ] ];
	
protected int[]getPropertyTableNumbers()

		return propertyTableNumbers;
	
protected int[]getPropertyTableNumbersInSelect()

		return propertyTableNumbers;
	
protected java.lang.StringgetSequentialSelect(java.lang.String entityName)

		return (String) sequentialSelectStringsByEntityName.get(entityName);
	
public java.lang.String[]getSubclassClosure()

		return subclassClosure;
	
protected int[]getSubclassColumnTableNumberClosure()

		return subclassColumnTableNumberClosure;
	
public java.lang.StringgetSubclassForDiscriminatorValue(java.lang.Object value)

		if (value==null) {
			return (String) subclassesByDiscriminatorValue.get(NULL_DISCRIMINATOR);
		}
		else {
			String result = (String) subclassesByDiscriminatorValue.get(value);
			if (result==null) result = (String) subclassesByDiscriminatorValue.get(NOT_NULL_DISCRIMINATOR);
			return result;
		}
	
protected int[]getSubclassFormulaTableNumberClosure()

		return subclassFormulaTableNumberClosure;
	
public java.lang.StringgetSubclassPropertyTableName(int i)

		return subclassTableNameClosure[ subclassPropertyTableNumberClosure[i] ];
	
protected intgetSubclassPropertyTableNumber(int i)

		return subclassPropertyTableNumberClosure[i];
	
private intgetSubclassPropertyTableNumber(java.lang.String propertyName, java.lang.String entityName)

		Type type = propertyMapping.toType(propertyName);
		if ( type.isAssociationType() && ( (AssociationType) type ).useLHSPrimaryKey() ) return 0;
		final Integer tabnum = (Integer) propertyTableNumbersByNameAndSubclass.get(entityName + '." + propertyName);
		return tabnum==null ? 0 : tabnum.intValue();
	
protected java.lang.String[]getSubclassTableKeyColumns(int j)

		return subclassTableKeyColumnClosure[j];
	
public java.lang.StringgetSubclassTableName(int j)

		return subclassTableNameClosure[j];
	
public intgetSubclassTableSpan()

		return subclassTableNameClosure.length;
	
protected java.lang.StringgetTableName(int j)

		return qualifiedTableNames[j];
	
public java.lang.StringgetTableName()

		return qualifiedTableNames[0];
	
public intgetTableSpan()

		return joinSpan;
	
public booleanhasSequentialSelect()

		return hasSequentialSelects;
	
protected booleanisClassOrSuperclassTable(int j)

		return isClassOrSuperclassTable[j];
	
protected booleanisDiscriminatorFormula()

		return discriminatorColumnName==null;
	
protected booleanisInverseSubclassTable(int j)

		return isInverseSubclassTable[j];
	
protected booleanisInverseTable(int j)

		return isInverseTable[j];
	
public booleanisMultiTable()

		return getTableSpan() > 1;
	
protected booleanisNullableSubclassTable(int j)

		return isNullableSubclassTable[j];
	
protected booleanisNullableTable(int j)

		return isNullableTable[j];
	
protected booleanisPropertyOfTable(int property, int j)

		return propertyTableNumbers[property]==j;
	
protected booleanisSubclassPropertyDeferred(java.lang.String propertyName, java.lang.String entityName)

		return hasSequentialSelects && 
			isSubclassTableSequentialSelect( getSubclassPropertyTableNumber(propertyName, entityName) );
	
protected booleanisSubclassTableLazy(int j)

		return subclassTableIsLazyClosure[j];
	
protected booleanisSubclassTableSequentialSelect(int j)

		return subclassTableSequentialSelect[j] && !isClassOrSuperclassTable[j];
	
protected booleanisTableCascadeDeleteEnabled(int j)

		return cascadeDeleteEnabled[j];
	
private booleanneedsDiscriminator()

		return forceDiscriminator || isInherited();
	
public java.lang.StringoneToManyFilterFragment(java.lang.String alias)

		return forceDiscriminator ?
			discriminatorFilterFragment(alias) :
			"";
	
public voidpostInstantiate()

		super.postInstantiate();
		if (hasSequentialSelects) {
			String[] entityNames = getSubclassClosure();
			for ( int i=1; i<entityNames.length; i++ ) {
				Loadable loadable = (Loadable) getFactory().getEntityPersister( entityNames[i] );
				if ( !loadable.isAbstract() ) { //perhaps not really necessary...
					String sequentialSelect = generateSequentialSelect(loadable);
					sequentialSelectStringsByEntityName.put( entityNames[i], sequentialSelect );
				}
			}
		}