📄 joinedsubclassentitypersister.java
字号:
//$Id: JoinedSubclassEntityPersister.java 8648 2005-11-23 18:33:37Z steveebersole $
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.CacheConcurrencyStrategy;
import org.hibernate.engine.Mapping;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.engine.Versioning;
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 CacheConcurrencyStrategy cache,
final SessionFactoryImplementor factory,
final Mapping mapping)
throws HibernateException {
super(persistentClass, cache, 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 attribute 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];
PersistentClass pc = persistentClass;
int jk = tableSpan-1;
while (pc!=null) {
customSQLInsert[jk] = pc.getCustomSQLInsert();
customSQLUpdate[jk] = pc.getCustomSQLUpdate();
customSQLDelete[jk] = pc.getCustomSQLDelete();
insertCallable[jk] = pc.isCustomInsertCallable();
updateCallable[jk] = pc.isCustomUpdateCallable();
deleteCallable[jk] = pc.isCustomDeleteCallable();
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(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -