📄 joinedsubclassentitypersister.java
字号:
//$Id: JoinedSubclassEntityPersister.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.Iterator;import java.util.Map;import org.hibernate.AssertionFailure;import org.hibernate.Hibernate;import org.hibernate.HibernateException;import org.hibernate.MappingException;import org.hibernate.QueryException;import org.hibernate.cache.access.EntityRegionAccessStrategy;import org.hibernate.engine.Mapping;import org.hibernate.engine.SessionFactoryImplementor;import org.hibernate.engine.Versioning;import org.hibernate.engine.ExecuteUpdateResultCheckStyle;import org.hibernate.mapping.Column;import org.hibernate.mapping.KeyValue;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.sql.CaseFragment;import org.hibernate.sql.SelectFragment;import org.hibernate.type.Type;import org.hibernate.util.ArrayHelper;/** * An <tt>EntityPersister</tt> implementing the normalized "table-per-subclass" * mapping strategy * * @author Gavin King */public class JoinedSubclassEntityPersister extends AbstractEntityPersister { // the class hierarchy structure private final int tableSpan; private final String[] tableNames; private final String[] naturalOrderTableNames; private final String[][] tableKeyColumns; private final String[][] naturalOrderTableKeyColumns; private final boolean[] naturalOrderCascadeDeleteEnabled; private final String[] spaces; private final String[] subclassClosure; private final String[] subclassTableNameClosure; private final String[][] subclassTableKeyColumnClosure; private final boolean[] isClassOrSuperclassTable; // properties of this class, including inherited properties private final int[] naturalOrderPropertyTableNumbers; private final int[] propertyTableNumbers; // the closure of all properties in the entire hierarchy including // subclasses and superclasses of this class private final int[] subclassPropertyTableNumberClosure; // the closure of all columns used by the entire hierarchy including // subclasses and superclasses of this class private final int[] subclassColumnTableNumberClosure; private final int[] subclassFormulaTableNumberClosure; // subclass discrimination works by assigning particular // values to certain combinations of null primary key // values in the outer join using an SQL CASE private final Map subclassesByDiscriminatorValue = new HashMap(); private final String[] discriminatorValues; private final String[] notNullColumnNames; private final int[] notNullColumnTableNumbers; private final String[] constraintOrderedTableNames; private final String[][] constraintOrderedKeyColumnNames; private final String discriminatorSQLString; //INITIALIZATION: public JoinedSubclassEntityPersister( final PersistentClass persistentClass, final EntityRegionAccessStrategy cacheAccessStrategy, final SessionFactoryImplementor factory, final Mapping mapping) throws HibernateException { super( persistentClass, cacheAccessStrategy, factory ); // DISCRIMINATOR final Object discriminatorValue; if ( persistentClass.isPolymorphic() ) { try { discriminatorValue = new Integer( persistentClass.getSubclassId() ); discriminatorSQLString = discriminatorValue.toString(); } catch (Exception e) { throw new MappingException("Could not format discriminator value to SQL string", e ); } } else { discriminatorValue = null; discriminatorSQLString = null; } if ( optimisticLockMode() > Versioning.OPTIMISTIC_LOCK_VERSION ) { throw new MappingException( "optimistic-lock=all|dirty not supported for joined-subclass mappings [" + getEntityName() + "]" ); } //MULTITABLES final int idColumnSpan = getIdentifierColumnSpan(); ArrayList tables = new ArrayList(); ArrayList keyColumns = new ArrayList(); ArrayList cascadeDeletes = new ArrayList(); Iterator titer = persistentClass.getTableClosureIterator(); Iterator kiter = persistentClass.getKeyClosureIterator(); while ( titer.hasNext() ) { Table tab = (Table) titer.next(); KeyValue key = (KeyValue) kiter.next(); String tabname = tab.getQualifiedName( factory.getDialect(), factory.getSettings().getDefaultCatalogName(), factory.getSettings().getDefaultSchemaName() ); tables.add(tabname); String[] keyCols = new String[idColumnSpan]; Iterator citer = key.getColumnIterator(); for ( int k=0; k<idColumnSpan; k++ ) { keyCols[k] = ( (Column) citer.next() ).getQuotedName( factory.getDialect() ); } keyColumns.add(keyCols); cascadeDeletes.add( new Boolean( key.isCascadeDeleteEnabled() && factory.getDialect().supportsCascadeDelete() ) ); } naturalOrderTableNames = ArrayHelper.toStringArray(tables); naturalOrderTableKeyColumns = ArrayHelper.to2DStringArray(keyColumns); naturalOrderCascadeDeleteEnabled = ArrayHelper.toBooleanArray(cascadeDeletes); ArrayList subtables = new ArrayList(); ArrayList isConcretes = new ArrayList(); keyColumns = new ArrayList(); titer = persistentClass.getSubclassTableClosureIterator(); while ( titer.hasNext() ) { Table tab = (Table) titer.next(); isConcretes.add( new Boolean( persistentClass.isClassOrSuperclassTable(tab) ) ); String tabname = tab.getQualifiedName( factory.getDialect(), factory.getSettings().getDefaultCatalogName(), factory.getSettings().getDefaultSchemaName() ); subtables.add(tabname); String[] key = new String[idColumnSpan]; Iterator citer = tab.getPrimaryKey().getColumnIterator(); for ( int k=0; k<idColumnSpan; k++ ) { key[k] = ( (Column) citer.next() ).getQuotedName( factory.getDialect() ); } keyColumns.add(key); } subclassTableNameClosure = ArrayHelper.toStringArray(subtables); subclassTableKeyColumnClosure = ArrayHelper.to2DStringArray(keyColumns); isClassOrSuperclassTable = ArrayHelper.toBooleanArray(isConcretes); constraintOrderedTableNames = new String[subclassTableNameClosure.length]; constraintOrderedKeyColumnNames = new String[subclassTableNameClosure.length][]; int currentPosition = 0; for ( int i = subclassTableNameClosure.length - 1; i >= 0 ; i--, currentPosition++ ) { constraintOrderedTableNames[currentPosition] = subclassTableNameClosure[i]; constraintOrderedKeyColumnNames[currentPosition] = subclassTableKeyColumnClosure[i]; } tableSpan = naturalOrderTableNames.length; tableNames = reverse(naturalOrderTableNames); tableKeyColumns = reverse(naturalOrderTableKeyColumns); reverse(subclassTableNameClosure, tableSpan); reverse(subclassTableKeyColumnClosure, tableSpan); spaces = ArrayHelper.join( tableNames, ArrayHelper.toStringArray( persistentClass.getSynchronizedTables() ) ); // Custom sql customSQLInsert = new String[tableSpan]; customSQLUpdate = new String[tableSpan]; customSQLDelete = new String[tableSpan]; insertCallable = new boolean[tableSpan]; updateCallable = new boolean[tableSpan]; deleteCallable = new boolean[tableSpan]; insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan]; PersistentClass pc = persistentClass; int jk = tableSpan-1; while (pc!=null) { customSQLInsert[jk] = pc.getCustomSQLInsert(); insertCallable[jk] = customSQLInsert[jk] != null && pc.isCustomInsertCallable(); insertResultCheckStyles[jk] = pc.getCustomSQLInsertCheckStyle() == null ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLInsert[jk], insertCallable[jk] ) : pc.getCustomSQLInsertCheckStyle(); customSQLUpdate[jk] = pc.getCustomSQLUpdate(); updateCallable[jk] = customSQLUpdate[jk] != null && pc.isCustomUpdateCallable(); updateResultCheckStyles[jk] = pc.getCustomSQLUpdateCheckStyle() == null ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[jk], updateCallable[jk] ) : pc.getCustomSQLUpdateCheckStyle(); customSQLDelete[jk] = pc.getCustomSQLDelete(); deleteCallable[jk] = customSQLDelete[jk] != null && pc.isCustomDeleteCallable(); deleteResultCheckStyles[jk] = pc.getCustomSQLDeleteCheckStyle() == null ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[jk], deleteCallable[jk] ) : pc.getCustomSQLDeleteCheckStyle(); jk--; pc = pc.getSuperclass(); } if ( jk != -1 ) { throw new AssertionFailure( "Tablespan does not match height of joined-subclass hiearchy." ); } // PROPERTIES int hydrateSpan = getPropertySpan(); naturalOrderPropertyTableNumbers = new int[hydrateSpan]; propertyTableNumbers = new int[hydrateSpan]; Iterator iter = persistentClass.getPropertyClosureIterator(); int i=0; while( iter.hasNext() ) { Property prop = (Property) iter.next(); String tabname = prop.getValue().getTable().getQualifiedName( factory.getDialect(), factory.getSettings().getDefaultCatalogName(), factory.getSettings().getDefaultSchemaName() ); propertyTableNumbers[i] = getTableId(tabname, tableNames); naturalOrderPropertyTableNumbers[i] = getTableId(tabname, naturalOrderTableNames); i++; } // subclass closure properties //TODO: code duplication with SingleTableEntityPersister ArrayList columnTableNumbers = new ArrayList(); ArrayList formulaTableNumbers = new ArrayList(); ArrayList propTableNumbers = new ArrayList(); iter = persistentClass.getSubclassPropertyClosureIterator(); while ( iter.hasNext() ) { Property prop = (Property) iter.next(); Table tab = prop.getValue().getTable(); String tabname = tab.getQualifiedName( factory.getDialect(), factory.getSettings().getDefaultCatalogName(), factory.getSettings().getDefaultSchemaName() ); Integer tabnum = new Integer( getTableId(tabname, subclassTableNameClosure) ); propTableNumbers.add(tabnum); Iterator citer = prop.getColumnIterator(); while ( citer.hasNext() ) { Selectable thing = (Selectable) citer.next(); if ( thing.isFormula() ) { formulaTableNumbers.add(tabnum); } else { columnTableNumbers.add(tabnum); } } } subclassColumnTableNumberClosure = ArrayHelper.toIntArray(columnTableNumbers); subclassPropertyTableNumberClosure = ArrayHelper.toIntArray(propTableNumbers); subclassFormulaTableNumberClosure = ArrayHelper.toIntArray(formulaTableNumbers); // SUBCLASSES int subclassSpan = persistentClass.getSubclassSpan() + 1; subclassClosure = new String[subclassSpan]; subclassClosure[subclassSpan-1] = getEntityName(); if ( persistentClass.isPolymorphic() ) { subclassesByDiscriminatorValue.put( discriminatorValue, getEntityName() ); discriminatorValues = new String[subclassSpan]; discriminatorValues[subclassSpan-1] = discriminatorSQLString; notNullColumnTableNumbers = new int[subclassSpan]; final int id = getTableId( persistentClass.getTable().getQualifiedName( factory.getDialect(), factory.getSettings().getDefaultCatalogName(), factory.getSettings().getDefaultSchemaName() ), subclassTableNameClosure
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -