📄 singletableentitypersister.java
字号:
//$Id: SingleTableEntityPersister.java 11398 2007-04-10 14:54:07Z steve.ebersole@jboss.com $package org.hibernate.persister.entity;import java.io.Serializable;import java.util.ArrayList;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.Map;import org.hibernate.EntityMode;import org.hibernate.HibernateException;import org.hibernate.MappingException;import org.hibernate.cache.access.EntityRegionAccessStrategy;import org.hibernate.engine.Mapping;import org.hibernate.engine.SessionFactoryImplementor;import org.hibernate.engine.ExecuteUpdateResultCheckStyle;import org.hibernate.mapping.Column;import org.hibernate.mapping.Formula;import org.hibernate.mapping.Join;import org.hibernate.mapping.PersistentClass;import org.hibernate.mapping.Property;import org.hibernate.mapping.Selectable;import org.hibernate.mapping.Subclass;import org.hibernate.mapping.Table;import org.hibernate.mapping.Value;import org.hibernate.sql.InFragment;import org.hibernate.sql.Insert;import org.hibernate.sql.SelectFragment;import org.hibernate.type.AssociationType;import org.hibernate.type.DiscriminatorType;import org.hibernate.type.Type;import org.hibernate.util.ArrayHelper;import org.hibernate.util.MarkerObject;/** * The default implementation of the <tt>EntityPersister</tt> 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 */public class SingleTableEntityPersister extends AbstractEntityPersister { // the class hierarchy structure 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; // properties of this class, including inherited properties private final int[] propertyTableNumbers; // the closure of all columns used by the entire hierarchy including // subclasses and superclasses of this class private final int[] subclassPropertyTableNumberClosure; private final int[] subclassColumnTableNumberClosure; private final int[] subclassFormulaTableNumberClosure; // discriminator column private final Map subclassesByDiscriminatorValue = new HashMap(); private final boolean forceDiscriminator; private final String discriminatorColumnName; private final String discriminatorFormula; private final String discriminatorFormulaTemplate; private final String discriminatorAlias; private final Type discriminatorType; private final String discriminatorSQLValue; private final boolean discriminatorInsertable; private final String[] constraintOrderedTableNames; private final String[][] constraintOrderedKeyColumnNames; //private final Map propertyTableNumbersByName = new HashMap(); private final Map propertyTableNumbersByNameAndSubclass = new HashMap(); private final Map sequentialSelectStringsByEntityName = new HashMap(); private static final Object NULL_DISCRIMINATOR = new MarkerObject("<null discriminator>"); private static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject("<not null discriminator>"); //INITIALIZATION: public SingleTableEntityPersister( final PersistentClass persistentClass, final EntityRegionAccessStrategy cacheAccessStrategy, final SessionFactoryImplementor factory, final Mapping mapping) throws HibernateException { super( persistentClass, cacheAccessStrategy, 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 {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -