Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » persister » entity » [javadoc | source]
    1   /*
    2    * Hibernate, Relational Persistence for Idiomatic Java
    3    *
    4    * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
    5    * indicated by the @author tags or express copyright attribution
    6    * statements applied by the authors.  All third-party contributions are
    7    * distributed under license by Red Hat Middleware LLC.
    8    *
    9    * This copyrighted material is made available to anyone wishing to use, modify,
   10    * copy, or redistribute it subject to the terms and conditions of the GNU
   11    * Lesser General Public License, as published by the Free Software Foundation.
   12    *
   13    * This program is distributed in the hope that it will be useful,
   14    * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   15    * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   16    * for more details.
   17    *
   18    * You should have received a copy of the GNU Lesser General Public License
   19    * along with this distribution; if not, write to:
   20    * Free Software Foundation, Inc.
   21    * 51 Franklin Street, Fifth Floor
   22    * Boston, MA  02110-1301  USA
   23    *
   24    */
   25   package org.hibernate.persister.entity;
   26   
   27   import java.io.Serializable;
   28   import java.util.ArrayList;
   29   import java.util.HashMap;
   30   import java.util.Iterator;
   31   import java.util.Map;
   32   
   33   import org.hibernate.AssertionFailure;
   34   import org.hibernate.Hibernate;
   35   import org.hibernate.HibernateException;
   36   import org.hibernate.MappingException;
   37   import org.hibernate.QueryException;
   38   import org.hibernate.cache.access.EntityRegionAccessStrategy;
   39   import org.hibernate.engine.Mapping;
   40   import org.hibernate.engine.SessionFactoryImplementor;
   41   import org.hibernate.engine.Versioning;
   42   import org.hibernate.engine.ExecuteUpdateResultCheckStyle;
   43   import org.hibernate.mapping.Column;
   44   import org.hibernate.mapping.KeyValue;
   45   import org.hibernate.mapping.PersistentClass;
   46   import org.hibernate.mapping.Property;
   47   import org.hibernate.mapping.Selectable;
   48   import org.hibernate.mapping.Subclass;
   49   import org.hibernate.mapping.Table;
   50   import org.hibernate.sql.CaseFragment;
   51   import org.hibernate.sql.SelectFragment;
   52   import org.hibernate.type.Type;
   53   import org.hibernate.util.ArrayHelper;
   54   
   55   /**
   56    * An <tt>EntityPersister</tt> implementing the normalized "table-per-subclass"
   57    * mapping strategy
   58    *
   59    * @author Gavin King
   60    */
   61   public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
   62   
   63   	// the class hierarchy structure
   64   	private final int tableSpan;
   65   	private final String[] tableNames;
   66   	private final String[] naturalOrderTableNames;
   67   	private final String[][] tableKeyColumns;
   68   	private final String[][] naturalOrderTableKeyColumns;
   69   	private final boolean[] naturalOrderCascadeDeleteEnabled;
   70   
   71   	private final String[] spaces;
   72   
   73   	private final String[] subclassClosure;
   74   
   75   	private final String[] subclassTableNameClosure;
   76   	private final String[][] subclassTableKeyColumnClosure;
   77   	private final boolean[] isClassOrSuperclassTable;
   78   
   79   	// properties of this class, including inherited properties
   80   	private final int[] naturalOrderPropertyTableNumbers;
   81   	private final int[] propertyTableNumbers;
   82   
   83   	// the closure of all properties in the entire hierarchy including
   84   	// subclasses and superclasses of this class
   85   	private final int[] subclassPropertyTableNumberClosure;
   86   
   87   	// the closure of all columns used by the entire hierarchy including
   88   	// subclasses and superclasses of this class
   89   	private final int[] subclassColumnTableNumberClosure;
   90   	private final int[] subclassFormulaTableNumberClosure;
   91   
   92   	// subclass discrimination works by assigning particular
   93   	// values to certain combinations of null primary key
   94   	// values in the outer join using an SQL CASE
   95   	private final Map subclassesByDiscriminatorValue = new HashMap();
   96   	private final String[] discriminatorValues;
   97   	private final String[] notNullColumnNames;
   98   	private final int[] notNullColumnTableNumbers;
   99   
  100   	private final String[] constraintOrderedTableNames;
  101   	private final String[][] constraintOrderedKeyColumnNames;
  102   
  103   	private final String discriminatorSQLString;
  104   
  105   	//INITIALIZATION:
  106   
  107   	public JoinedSubclassEntityPersister(
  108   			final PersistentClass persistentClass,
  109   			final EntityRegionAccessStrategy cacheAccessStrategy,
  110   			final SessionFactoryImplementor factory,
  111   			final Mapping mapping) throws HibernateException {
  112   
  113   		super( persistentClass, cacheAccessStrategy, factory );
  114   
  115   		// DISCRIMINATOR
  116   
  117   		final Object discriminatorValue;
  118   		if ( persistentClass.isPolymorphic() ) {
  119   			try {
  120   				discriminatorValue = new Integer( persistentClass.getSubclassId() );
  121   				discriminatorSQLString = discriminatorValue.toString();
  122   			}
  123   			catch (Exception e) {
  124   				throw new MappingException("Could not format discriminator value to SQL string", e );
  125   			}
  126   		}
  127   		else {
  128   			discriminatorValue = null;
  129   			discriminatorSQLString = null;
  130   		}
  131   
  132   		if ( optimisticLockMode() > Versioning.OPTIMISTIC_LOCK_VERSION ) {
  133   			throw new MappingException( "optimistic-lock=all|dirty not supported for joined-subclass mappings [" + getEntityName() + "]" );
  134   		}
  135   
  136   		//MULTITABLES
  137   
  138   		final int idColumnSpan = getIdentifierColumnSpan();
  139   
  140   		ArrayList tables = new ArrayList();
  141   		ArrayList keyColumns = new ArrayList();
  142   		ArrayList cascadeDeletes = new ArrayList();
  143   		Iterator titer = persistentClass.getTableClosureIterator();
  144   		Iterator kiter = persistentClass.getKeyClosureIterator();
  145   		while ( titer.hasNext() ) {
  146   			Table tab = (Table) titer.next();
  147   			KeyValue key = (KeyValue) kiter.next();
  148   			String tabname = tab.getQualifiedName(
  149   					factory.getDialect(),
  150   					factory.getSettings().getDefaultCatalogName(),
  151   					factory.getSettings().getDefaultSchemaName()
  152   			);
  153   			tables.add(tabname);
  154   			String[] keyCols = new String[idColumnSpan];
  155   			Iterator citer = key.getColumnIterator();
  156   			for ( int k=0; k<idColumnSpan; k++ ) {
  157   				keyCols[k] = ( (Column) citer.next() ).getQuotedName( factory.getDialect() );
  158   			}
  159   			keyColumns.add(keyCols);
  160   			cascadeDeletes.add( new Boolean( key.isCascadeDeleteEnabled() && factory.getDialect().supportsCascadeDelete() ) );
  161   		}
  162   		naturalOrderTableNames = ArrayHelper.toStringArray(tables);
  163   		naturalOrderTableKeyColumns = ArrayHelper.to2DStringArray(keyColumns);
  164   		naturalOrderCascadeDeleteEnabled = ArrayHelper.toBooleanArray(cascadeDeletes);
  165   
  166   		ArrayList subtables = new ArrayList();
  167   		ArrayList isConcretes = new ArrayList();
  168   		keyColumns = new ArrayList();
  169   		titer = persistentClass.getSubclassTableClosureIterator();
  170   		while ( titer.hasNext() ) {
  171   			Table tab = (Table) titer.next();
  172   			isConcretes.add( new Boolean( persistentClass.isClassOrSuperclassTable(tab) ) );
  173   			String tabname = tab.getQualifiedName(
  174   					factory.getDialect(),
  175   					factory.getSettings().getDefaultCatalogName(),
  176   					factory.getSettings().getDefaultSchemaName()
  177   			);
  178   			subtables.add(tabname);
  179   			String[] key = new String[idColumnSpan];
  180   			Iterator citer = tab.getPrimaryKey().getColumnIterator();
  181   			for ( int k=0; k<idColumnSpan; k++ ) {
  182   				key[k] = ( (Column) citer.next() ).getQuotedName( factory.getDialect() );
  183   			}
  184   			keyColumns.add(key);
  185   		}
  186   		subclassTableNameClosure = ArrayHelper.toStringArray(subtables);
  187   		subclassTableKeyColumnClosure = ArrayHelper.to2DStringArray(keyColumns);
  188   		isClassOrSuperclassTable = ArrayHelper.toBooleanArray(isConcretes);
  189   
  190   		constraintOrderedTableNames = new String[subclassTableNameClosure.length];
  191   		constraintOrderedKeyColumnNames = new String[subclassTableNameClosure.length][];
  192   		int currentPosition = 0;
  193   		for ( int i = subclassTableNameClosure.length - 1; i >= 0 ; i--, currentPosition++ ) {
  194   			constraintOrderedTableNames[currentPosition] = subclassTableNameClosure[i];
  195   			constraintOrderedKeyColumnNames[currentPosition] = subclassTableKeyColumnClosure[i];
  196   		}
  197   
  198   		tableSpan = naturalOrderTableNames.length;
  199   		tableNames = reverse(naturalOrderTableNames);
  200   		tableKeyColumns = reverse(naturalOrderTableKeyColumns);
  201   		reverse(subclassTableNameClosure, tableSpan);
  202   		reverse(subclassTableKeyColumnClosure, tableSpan);
  203   
  204   		spaces = ArrayHelper.join(
  205   				tableNames,
  206   				ArrayHelper.toStringArray( persistentClass.getSynchronizedTables() )
  207   		);
  208   
  209   		// Custom sql
  210   		customSQLInsert = new String[tableSpan];
  211   		customSQLUpdate = new String[tableSpan];
  212   		customSQLDelete = new String[tableSpan];
  213   		insertCallable = new boolean[tableSpan];
  214   		updateCallable = new boolean[tableSpan];
  215   		deleteCallable = new boolean[tableSpan];
  216   		insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];
  217   		updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];
  218   		deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[tableSpan];
  219   
  220   		PersistentClass pc = persistentClass;
  221   		int jk = tableSpan-1;
  222   		while (pc!=null) {
  223   			customSQLInsert[jk] = pc.getCustomSQLInsert();
  224   			insertCallable[jk] = customSQLInsert[jk] != null && pc.isCustomInsertCallable();
  225   			insertResultCheckStyles[jk] = pc.getCustomSQLInsertCheckStyle() == null
  226   			                              ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLInsert[jk], insertCallable[jk] )
  227   		                                  : pc.getCustomSQLInsertCheckStyle();
  228   			customSQLUpdate[jk] = pc.getCustomSQLUpdate();
  229   			updateCallable[jk] = customSQLUpdate[jk] != null && pc.isCustomUpdateCallable();
  230   			updateResultCheckStyles[jk] = pc.getCustomSQLUpdateCheckStyle() == null
  231   			                              ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLUpdate[jk], updateCallable[jk] )
  232   		                                  : pc.getCustomSQLUpdateCheckStyle();
  233   			customSQLDelete[jk] = pc.getCustomSQLDelete();
  234   			deleteCallable[jk] = customSQLDelete[jk] != null && pc.isCustomDeleteCallable();
  235   			deleteResultCheckStyles[jk] = pc.getCustomSQLDeleteCheckStyle() == null
  236   			                              ? ExecuteUpdateResultCheckStyle.determineDefault( customSQLDelete[jk], deleteCallable[jk] )
  237   		                                  : pc.getCustomSQLDeleteCheckStyle();
  238   			jk--;
  239   			pc = pc.getSuperclass();
  240   		}
  241   		if ( jk != -1 ) {
  242   			throw new AssertionFailure( "Tablespan does not match height of joined-subclass hiearchy." );
  243   		}
  244   
  245   		// PROPERTIES
  246   
  247   		int hydrateSpan = getPropertySpan();
  248   		naturalOrderPropertyTableNumbers = new int[hydrateSpan];
  249   		propertyTableNumbers = new int[hydrateSpan];
  250   		Iterator iter = persistentClass.getPropertyClosureIterator();
  251   		int i=0;
  252   		while( iter.hasNext() ) {
  253   			Property prop = (Property) iter.next();
  254   			String tabname = prop.getValue().getTable().getQualifiedName(
  255   				factory.getDialect(),
  256   				factory.getSettings().getDefaultCatalogName(),
  257   				factory.getSettings().getDefaultSchemaName()
  258   			);
  259   			propertyTableNumbers[i] = getTableId(tabname, tableNames);
  260   			naturalOrderPropertyTableNumbers[i] = getTableId(tabname, naturalOrderTableNames);
  261   			i++;
  262   		}
  263   
  264   		// subclass closure properties
  265   
  266   		//TODO: code duplication with SingleTableEntityPersister
  267   
  268   		ArrayList columnTableNumbers = new ArrayList();
  269   		ArrayList formulaTableNumbers = new ArrayList();
  270   		ArrayList propTableNumbers = new ArrayList();
  271   
  272   		iter = persistentClass.getSubclassPropertyClosureIterator();
  273   		while ( iter.hasNext() ) {
  274   			Property prop = (Property) iter.next();
  275   			Table tab = prop.getValue().getTable();
  276   			String tabname = tab.getQualifiedName(
  277   					factory.getDialect(),
  278   					factory.getSettings().getDefaultCatalogName(),
  279   					factory.getSettings().getDefaultSchemaName()
  280   			);
  281   			Integer tabnum = new Integer( getTableId(tabname, subclassTableNameClosure) );
  282   			propTableNumbers.add(tabnum);
  283   
  284   			Iterator citer = prop.getColumnIterator();
  285   			while ( citer.hasNext() ) {
  286   				Selectable thing = (Selectable) citer.next();
  287   				if ( thing.isFormula() ) {
  288   					formulaTableNumbers.add(tabnum);
  289   				}
  290   				else {
  291   					columnTableNumbers.add(tabnum);
  292   				}
  293   			}
  294   
  295   		}
  296   
  297   		subclassColumnTableNumberClosure = ArrayHelper.toIntArray(columnTableNumbers);
  298   		subclassPropertyTableNumberClosure = ArrayHelper.toIntArray(propTableNumbers);
  299   		subclassFormulaTableNumberClosure = ArrayHelper.toIntArray(formulaTableNumbers);
  300   
  301   		// SUBCLASSES
  302   
  303   		int subclassSpan = persistentClass.getSubclassSpan() + 1;
  304   		subclassClosure = new String[subclassSpan];
  305   		subclassClosure[subclassSpan-1] = getEntityName();
  306   		if ( persistentClass.isPolymorphic() ) {
  307   			subclassesByDiscriminatorValue.put( discriminatorValue, getEntityName() );
  308   			discriminatorValues = new String[subclassSpan];
  309   			discriminatorValues[subclassSpan-1] = discriminatorSQLString;
  310   			notNullColumnTableNumbers = new int[subclassSpan];
  311   			final int id = getTableId(
  312   				persistentClass.getTable().getQualifiedName(
  313   						factory.getDialect(),
  314   						factory.getSettings().getDefaultCatalogName(),
  315   						factory.getSettings().getDefaultSchemaName()
  316   				),
  317   				subclassTableNameClosure
  318   			);
  319   			notNullColumnTableNumbers[subclassSpan-1] = id;
  320   			notNullColumnNames = new String[subclassSpan];
  321   			notNullColumnNames[subclassSpan-1] =  subclassTableKeyColumnClosure[id][0]; //( (Column) model.getTable().getPrimaryKey().getColumnIterator().next() ).getName();
  322   		}
  323   		else {
  324   			discriminatorValues = null;
  325   			notNullColumnTableNumbers = null;
  326   			notNullColumnNames = null;
  327   		}
  328   
  329   		iter = persistentClass.getSubclassIterator();
  330   		int k=0;
  331   		while ( iter.hasNext() ) {
  332   			Subclass sc = (Subclass) iter.next();
  333   			subclassClosure[k] = sc.getEntityName();
  334   			try {
  335   				if ( persistentClass.isPolymorphic() ) {
  336   					// we now use subclass ids that are consistent across all
  337   					// persisters for a class hierarchy, so that the use of
  338   					// "foo.class = Bar" works in HQL
  339   					Integer subclassId = new Integer( sc.getSubclassId() );//new Integer(k+1);
  340   					subclassesByDiscriminatorValue.put( subclassId, sc.getEntityName() );
  341   					discriminatorValues[k] = subclassId.toString();
  342   					int id = getTableId(
  343   						sc.getTable().getQualifiedName(
  344   								factory.getDialect(),
  345   								factory.getSettings().getDefaultCatalogName(),
  346   								factory.getSettings().getDefaultSchemaName()
  347   						),
  348   						subclassTableNameClosure
  349   					);
  350   					notNullColumnTableNumbers[k] = id;
  351   					notNullColumnNames[k] = subclassTableKeyColumnClosure[id][0]; //( (Column) sc.getTable().getPrimaryKey().getColumnIterator().next() ).getName();
  352   				}
  353   			}
  354   			catch (Exception e) {
  355   				throw new MappingException("Error parsing discriminator value", e );
  356   			}
  357   			k++;
  358   		}
  359   
  360   		initLockers();
  361   
  362   		initSubclassPropertyAliasesMap(persistentClass);
  363   
  364   		postConstruct(mapping);
  365   
  366   	}
  367   
  368   	/*public void postInstantiate() throws MappingException {
  369   		super.postInstantiate();
  370   		//TODO: other lock modes?
  371   		loader = createEntityLoader(LockMode.NONE, CollectionHelper.EMPTY_MAP);
  372   	}*/
  373   
  374   	public String getSubclassPropertyTableName(int i) {
  375   		return subclassTableNameClosure[ subclassPropertyTableNumberClosure[i] ];
  376   	}
  377   
  378   	public Type getDiscriminatorType() {
  379   		return Hibernate.INTEGER;
  380   	}
  381   
  382   	public String getDiscriminatorSQLValue() {
  383   		return discriminatorSQLString;
  384   	}
  385   
  386   
  387   	public String getSubclassForDiscriminatorValue(Object value) {
  388   		return (String) subclassesByDiscriminatorValue.get(value);
  389   	}
  390   
  391   	public Serializable[] getPropertySpaces() {
  392   		return spaces; // don't need subclass tables, because they can't appear in conditions
  393   	}
  394   
  395   
  396   	protected String getTableName(int j) {
  397   		return naturalOrderTableNames[j];
  398   	}
  399   
  400   	protected String[] getKeyColumns(int j) {
  401   		return naturalOrderTableKeyColumns[j];
  402   	}
  403   
  404   	protected boolean isTableCascadeDeleteEnabled(int j) {
  405   		return naturalOrderCascadeDeleteEnabled[j];
  406   	}
  407   
  408   	protected boolean isPropertyOfTable(int property, int j) {
  409   		return naturalOrderPropertyTableNumbers[property]==j;
  410   	}
  411   
  412   	/**
  413   	 * Load an instance using either the <tt>forUpdateLoader</tt> or the outer joining <tt>loader</tt>,
  414   	 * depending upon the value of the <tt>lock</tt> parameter
  415   	 */
  416   	/*public Object load(Serializable id,	Object optionalObject, LockMode lockMode, SessionImplementor session)
  417   	throws HibernateException {
  418   
  419   		if ( log.isTraceEnabled() ) log.trace( "Materializing entity: " + MessageHelper.infoString(this, id) );
  420   
  421   		final UniqueEntityLoader loader = hasQueryLoader() ?
  422   				getQueryLoader() :
  423   				this.loader;
  424   		try {
  425   
  426   			final Object result = loader.load(id, optionalObject, session);
  427   
  428   			if (result!=null) lock(id, getVersion(result), result, lockMode, session);
  429   
  430   			return result;
  431   
  432   		}
  433   		catch (SQLException sqle) {
  434   			throw new JDBCException( "could not load by id: " +  MessageHelper.infoString(this, id), sqle );
  435   		}
  436   	}*/
  437   
  438   	private static final void reverse(Object[] objects, int len) {
  439   		Object[] temp = new Object[len];
  440   		for (int i=0; i<len; i++) {
  441   			temp[i] = objects[len-i-1];
  442   		}
  443   		for (int i=0; i<len; i++) {
  444   			objects[i] = temp[i];
  445   		}
  446   	}
  447   
  448   	private static final String[] reverse(String[] objects) {
  449   		int len = objects.length;
  450   		String[] temp = new String[len];
  451   		for (int i=0; i<len; i++) {
  452   			temp[i] = objects[len-i-1];
  453   		}
  454   		return temp;
  455   	}
  456   
  457   	private static final String[][] reverse(String[][] objects) {
  458   		int len = objects.length;
  459   		String[][] temp = new String[len][];
  460   		for (int i=0; i<len; i++) {
  461   			temp[i] = objects[len-i-1];
  462   		}
  463   		return temp;
  464   	}
  465   
  466   	public String fromTableFragment(String alias) {
  467   		return getTableName() + ' ' + alias;
  468   	}
  469   
  470   	public String getTableName() {
  471   		return tableNames[0];
  472   	}
  473   
  474   	private static int getTableId(String tableName, String[] tables) {
  475   		for ( int j=0; j<tables.length; j++ ) {
  476   			if ( tableName.equals( tables[j] ) ) {
  477   				return j;
  478   			}
  479   		}
  480   		throw new AssertionFailure("Table " + tableName + " not found");
  481   	}
  482   
  483   	public void addDiscriminatorToSelect(SelectFragment select, String name, String suffix) {
  484   		if ( hasSubclasses() ) {
  485   			select.setExtraSelectList( discriminatorFragment(name), getDiscriminatorAlias() );
  486   		}
  487   	}
  488   
  489   	private CaseFragment discriminatorFragment(String alias) {
  490   		CaseFragment cases = getFactory().getDialect().createCaseFragment();
  491   
  492   		for ( int i=0; i<discriminatorValues.length; i++ ) {
  493   			cases.addWhenColumnNotNull(
  494   				generateTableAlias( alias, notNullColumnTableNumbers[i] ),
  495   				notNullColumnNames[i],
  496   				discriminatorValues[i]
  497   			);
  498   		}
  499   
  500   		return cases;
  501   	}
  502   
  503   	public String filterFragment(String alias) {
  504   		return hasWhere() ?
  505   			" and " + getSQLWhereString( generateFilterConditionAlias( alias ) ) :
  506   			"";
  507   	}
  508   
  509   	public String generateFilterConditionAlias(String rootAlias) {
  510   		return generateTableAlias( rootAlias, tableSpan-1 );
  511   	}
  512   
  513   	public String[] getIdentifierColumnNames() {
  514   		return tableKeyColumns[0];
  515   	}
  516   
  517   	public String[] toColumns(String alias, String propertyName) throws QueryException {
  518   
  519   		if ( ENTITY_CLASS.equals(propertyName) ) {
  520   			// This doesn't actually seem to work but it *might*
  521   			// work on some dbs. Also it doesn't work if there
  522   			// are multiple columns of results because it
  523   			// is not accounting for the suffix:
  524   			// return new String[] { getDiscriminatorColumnName() };
  525   
  526   			return new String[] { discriminatorFragment(alias).toFragmentString() };
  527   		}
  528   		else {
  529   			return super.toColumns(alias, propertyName);
  530   		}
  531   
  532   	}
  533   
  534   	protected int[] getPropertyTableNumbersInSelect() {
  535   		return propertyTableNumbers;
  536   	}
  537   
  538   	protected int getSubclassPropertyTableNumber(int i) {
  539   		return subclassPropertyTableNumberClosure[i];
  540   	}
  541   
  542   	public int getTableSpan() {
  543   		return tableSpan;
  544   	}
  545   
  546   	public boolean isMultiTable() {
  547   		return true;
  548   	}
  549   
  550   	protected int[] getSubclassColumnTableNumberClosure() {
  551   		return subclassColumnTableNumberClosure;
  552   	}
  553   
  554   	protected int[] getSubclassFormulaTableNumberClosure() {
  555   		return subclassFormulaTableNumberClosure;
  556   	}
  557   
  558   	protected int[] getPropertyTableNumbers() {
  559   		return naturalOrderPropertyTableNumbers;
  560   	}
  561   
  562   	protected String[] getSubclassTableKeyColumns(int j) {
  563   		return subclassTableKeyColumnClosure[j];
  564   	}
  565   
  566   	public String getSubclassTableName(int j) {
  567   		return subclassTableNameClosure[j];
  568   	}
  569   
  570   	public int getSubclassTableSpan() {
  571   		return subclassTableNameClosure.length;
  572   	}
  573   
  574   	protected boolean isClassOrSuperclassTable(int j) {
  575   		return isClassOrSuperclassTable[j];
  576   	}
  577   
  578   	public String getPropertyTableName(String propertyName) {
  579   		Integer index = getEntityMetamodel().getPropertyIndexOrNull(propertyName);
  580   		if ( index == null ) {
  581   			return null;
  582   		}
  583   		return tableNames[ propertyTableNumbers[ index.intValue() ] ];
  584   	}
  585   
  586   	public String[] getConstraintOrderedTableNameClosure() {
  587   		return constraintOrderedTableNames;
  588   	}
  589   
  590   	public String[][] getContraintOrderedTableKeyColumnClosure() {
  591   		return constraintOrderedKeyColumnNames;
  592   	}
  593   
  594   	public String getRootTableName() {
  595   		return naturalOrderTableNames[0];
  596   	}
  597   
  598   	public String getRootTableAlias(String drivingAlias) {
  599   		return generateTableAlias( drivingAlias, getTableId( getRootTableName(), tableNames ) );
  600   	}
  601   
  602   	public Declarer getSubclassPropertyDeclarer(String propertyPath) {
  603   		if ( "class".equals( propertyPath ) ) {
  604   			// special case where we need to force incloude all subclass joins
  605   			return Declarer.SUBCLASS;
  606   		}
  607   		return super.getSubclassPropertyDeclarer( propertyPath );
  608   	}
  609   }

Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » persister » entity » [javadoc | source]