⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 joinedsubclassentitypersister.java

📁 hibernate-3.1.3-all-src.zip 面向对象的访问数据库工具
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
//$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 + -