HHH-6411 : Integrate new metamodel into SingleTableEntityPersister

This commit is contained in:
Gail Badner 2011-07-06 15:08:36 -07:00
parent d981f54942
commit 5457b6c707
3 changed files with 569 additions and 96 deletions

View File

@ -540,8 +540,6 @@ public final class SessionFactoryImpl
this.currentSessionContext = null;
this.sqlFunctionRegistry = null;
this.transactionEnvironment = null;
this.jdbcServices = null;
this.dialect = null;
this.sessionFactoryOptions = sessionFactoryOptions;
@ -560,6 +558,9 @@ public final class SessionFactoryImpl
.getService( SessionFactoryServiceRegistryFactory.class )
.buildServiceRegistry( this, metadata );
this.jdbcServices = this.serviceRegistry.getService( JdbcServices.class );
this.dialect = this.jdbcServices.getDialect();
// TODO: get SQL functions from a new service
// this.sqlFunctionRegistry = new SQLFunctionRegistry( getDialect(), cfg.getSqlFunctions() );
@ -754,8 +755,7 @@ public final class SessionFactoryImpl
Iterator iter = entityPersisters.values().iterator();
while ( iter.hasNext() ) {
final EntityPersister persister = ( ( EntityPersister ) iter.next() );
// TODO: broken
//persister.postInstantiate();
persister.postInstantiate();
registerEntityNameResolvers( persister );
}
@ -967,11 +967,9 @@ public final class SessionFactoryImpl
throw new IllegalStateException( "Cannot determine dialect because serviceRegistry is null." );
}
return dialect;
//return getJdbcServices().getDialect();
}
public Interceptor getInterceptor()
{
public Interceptor getInterceptor() {
return sessionFactoryOptions.getInterceptor();
}

View File

@ -42,10 +42,13 @@ import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.FetchMode;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.function.SQLFunctionRegistry;
import org.hibernate.engine.internal.Versioning;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
import org.hibernate.engine.spi.FilterDefinition;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.Mapping;
import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -92,7 +95,11 @@ import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Selectable;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.metamodel.binding.AttributeBinding;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.relational.DerivedValue;
import org.hibernate.metamodel.relational.Identifier;
import org.hibernate.metamodel.relational.SimpleValue;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.property.BackrefPropertyAccessor;
import org.hibernate.sql.Alias;
@ -771,62 +778,233 @@ public abstract class AbstractEntityPersister
new StructuredCacheEntry(this) :
new UnstructuredCacheEntry();
this.entityMetamodel = new EntityMetamodel( entityBinding, factory );
rootTableKeyColumnNames = null;
rootTableKeyColumnReaders = null;
rootTableKeyColumnReaderTemplates = null;
identifierAliases = null;
identifierColumnSpan = -1;
int batch = entityBinding.getBatchSize();
if ( batch == -1 ) {
batch = factory.getSettings().getDefaultBatchFetchSize();
}
batchSize = batch;
hasSubselectLoadableCollections = entityBinding.hasSubselectLoadableCollections();
propertyMapping = new BasicEntityPropertyMapping( this );
// IDENTIFIER
identifierColumnSpan = entityBinding.getEntityIdentifier().getValueBinding().getValuesSpan();
rootTableKeyColumnNames = new String[identifierColumnSpan];
rootTableKeyColumnReaders = new String[identifierColumnSpan];
rootTableKeyColumnReaderTemplates = new String[identifierColumnSpan];
identifierAliases = new String[identifierColumnSpan];
rowIdName = entityBinding.getRowId();
loaderName = entityBinding.getLoaderName();
int i = 0;
for ( org.hibernate.metamodel.relational.Column col : entityBinding.getBaseTable().getPrimaryKey().getColumns() ) {
rootTableKeyColumnNames[i] = col.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() );
if ( col.getReadFragment() == null ) {
rootTableKeyColumnReaders[i] = rootTableKeyColumnNames[i];
rootTableKeyColumnReaderTemplates[i] = getTemplateFromColumn( col, factory );
}
else {
rootTableKeyColumnReaders[i] = col.getReadFragment();
rootTableKeyColumnReaderTemplates[i] = getTemplateFromString( col.getReadFragment(), factory );
}
// TODO: Fix when HHH-6337 is fixed; for now assume entityBinding is the root
// identifierAliases[i] = col.getAlias( factory.getDialect(), entityBinding.getRootEntityBinding().getBaseTable() );
identifierAliases[i] = col.getAlias( factory.getDialect() );
i++;
}
// VERSION
if ( entityBinding.isVersioned() ) {
// Use AttributeBinding.getValues() due to HHH-6380
Iterator<SimpleValue> valueIterator = entityBinding.getVersioningValueBinding().getValues().iterator();
SimpleValue versionValue = valueIterator.next();
if ( ! ( versionValue instanceof org.hibernate.metamodel.relational.Column ) || valueIterator.hasNext() ) {
throw new MappingException( "Version must be a single column value." );
}
org.hibernate.metamodel.relational.Column versionColumn =
( org.hibernate.metamodel.relational.Column ) versionValue;
versionColumnName = versionColumn.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() );
}
else {
versionColumnName = null;
hasFormulaProperties = false;
batchSize = -1;
hasSubselectLoadableCollections = false;
rowIdName = null;
lazyProperties = null;
sqlWhereString = null;
sqlWhereStringTemplate = null;
propertyColumnSpans = null;
propertySubclassNames = null;
propertyColumnAliases = null;
propertyColumnNames = null;
propertyColumnFormulaTemplates = null;
propertyColumnReaderTemplates = null;
propertyColumnWriters = null;
propertyColumnUpdateable = null;
propertyColumnInsertable = null;
propertyUniqueness = null;
propertySelectable = null;
lazyPropertyNames = null;
lazyPropertyNumbers = null;
lazyPropertyTypes = null;
lazyPropertyColumnAliases = null;
subclassPropertyNameClosure = null;
subclassPropertySubclassNameClosure = null;
subclassPropertyTypeClosure = null;
subclassPropertyFormulaTemplateClosure = null;
subclassPropertyColumnNameClosure = null;
subclassPropertyColumnReaderClosure = null;
subclassPropertyColumnReaderTemplateClosure = null;
subclassPropertyFetchModeClosure = null;
subclassPropertyNullabilityClosure = null;
propertyDefinedOnSubclass = null;
subclassPropertyColumnNumberClosure = null;
subclassPropertyFormulaNumberClosure = null;
subclassPropertyCascadeStyleClosure = null;
subclassColumnClosure = null;
subclassColumnLazyClosure = null;
subclassColumnAliasClosure = null;
subclassColumnSelectableClosure = null;
subclassColumnReaderTemplateClosure = null;
subclassFormulaClosure = null;
subclassFormulaTemplateClosure = null;
subclassFormulaAliasClosure = null;
subclassFormulaLazyClosure = null;
filterHelper = null;
loaderName = null;
queryLoader = null;
}
//WHERE STRING
sqlWhereString = StringHelper.isNotEmpty( entityBinding.getWhereFilter() ) ? "( " + entityBinding.getWhereFilter() + ") " : null;
sqlWhereStringTemplate = getTemplateFromString( sqlWhereString, factory );
// PROPERTIES
final boolean lazyAvailable = isInstrumented();
int hydrateSpan = entityMetamodel.getPropertySpan();
propertyColumnSpans = new int[hydrateSpan];
propertySubclassNames = new String[hydrateSpan];
propertyColumnAliases = new String[hydrateSpan][];
propertyColumnNames = new String[hydrateSpan][];
propertyColumnFormulaTemplates = new String[hydrateSpan][];
propertyColumnReaderTemplates = new String[hydrateSpan][];
propertyColumnWriters = new String[hydrateSpan][];
propertyUniqueness = new boolean[hydrateSpan];
propertySelectable = new boolean[hydrateSpan];
propertyColumnUpdateable = new boolean[hydrateSpan][];
propertyColumnInsertable = new boolean[hydrateSpan][];
HashSet thisClassProperties = new HashSet();
lazyProperties = new HashSet();
ArrayList lazyNames = new ArrayList();
ArrayList lazyNumbers = new ArrayList();
ArrayList lazyTypes = new ArrayList();
ArrayList lazyColAliases = new ArrayList();
i = 0;
boolean foundFormula = false;
for ( AttributeBinding prop : entityBinding.getAttributeBindingClosure() ) {
if ( prop == entityBinding.getEntityIdentifier().getValueBinding() ) {
// entity identifier is not considered a "normal" property
continue;
}
thisClassProperties.add( prop );
int span = prop.getValuesSpan();
propertyColumnSpans[i] = span;
propertySubclassNames[i] = prop.getEntityBinding().getEntity().getName();
String[] colNames = new String[span];
String[] colAliases = new String[span];
String[] colReaderTemplates = new String[span];
String[] colWriters = new String[span];
String[] formulaTemplates = new String[span];
int k = 0;
for ( SimpleValue thing : prop.getValues() ) {
colAliases[k] = thing.getAlias( factory.getDialect() );
if ( thing instanceof DerivedValue ) {
foundFormula = true;
formulaTemplates[ k ] = getTemplateFromString( ( (DerivedValue) thing ).getExpression(), factory );
}
else {
org.hibernate.metamodel.relational.Column col = ( org.hibernate.metamodel.relational.Column ) thing;
colNames[k] = col.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() );
colReaderTemplates[k] = getTemplateFromColumn( col, factory );
colWriters[k] = col.getWriteFragment();
}
k++;
}
propertyColumnNames[i] = colNames;
propertyColumnFormulaTemplates[i] = formulaTemplates;
propertyColumnReaderTemplates[i] = colReaderTemplates;
propertyColumnWriters[i] = colWriters;
propertyColumnAliases[i] = colAliases;
if ( lazyAvailable && prop.isLazy() ) {
lazyProperties.add( prop.getAttribute().getName() );
lazyNames.add( prop.getAttribute().getName() );
lazyNumbers.add( i );
lazyTypes.add( prop.getHibernateTypeDescriptor().getExplicitType());
lazyColAliases.add( colAliases );
}
propertyColumnUpdateable[i] = prop.getColumnUpdateability();
propertyColumnInsertable[i] = prop.getColumnInsertability();
// TODO: fix this when backrefs are working
//propertySelectable[i] = prop.isBackRef();
propertySelectable[i] = true;
propertyUniqueness[i] = prop.isAlternateUniqueKey();
i++;
}
hasFormulaProperties = foundFormula;
lazyPropertyColumnAliases = ArrayHelper.to2DStringArray( lazyColAliases );
lazyPropertyNames = ArrayHelper.toStringArray( lazyNames );
lazyPropertyNumbers = ArrayHelper.toIntArray( lazyNumbers );
lazyPropertyTypes = ArrayHelper.toTypeArray( lazyTypes );
// SUBCLASS PROPERTY CLOSURE
ArrayList columns = new ArrayList();
ArrayList columnsLazy = new ArrayList();
ArrayList columnReaderTemplates = new ArrayList();
ArrayList aliases = new ArrayList();
ArrayList formulas = new ArrayList();
ArrayList formulaAliases = new ArrayList();
ArrayList formulaTemplates = new ArrayList();
ArrayList formulasLazy = new ArrayList();
ArrayList types = new ArrayList();
ArrayList names = new ArrayList();
ArrayList classes = new ArrayList();
ArrayList templates = new ArrayList();
ArrayList propColumns = new ArrayList();
ArrayList propColumnReaders = new ArrayList();
ArrayList propColumnReaderTemplates = new ArrayList();
ArrayList<FetchMode> joinedFetchesList = new ArrayList<FetchMode>();
ArrayList<CascadeStyle> cascades = new ArrayList<CascadeStyle>();
ArrayList<Boolean> definedBySubclass = new ArrayList<Boolean>();
ArrayList propColumnNumbers = new ArrayList();
ArrayList propFormulaNumbers = new ArrayList();
ArrayList columnSelectables = new ArrayList();
ArrayList propNullables = new ArrayList();
subclassColumnClosure = ArrayHelper.toStringArray( columns );
subclassColumnAliasClosure = ArrayHelper.toStringArray( aliases );
subclassColumnLazyClosure = ArrayHelper.toBooleanArray( columnsLazy );
subclassColumnSelectableClosure = ArrayHelper.toBooleanArray( columnSelectables );
subclassColumnReaderTemplateClosure = ArrayHelper.toStringArray( columnReaderTemplates );
subclassFormulaClosure = ArrayHelper.toStringArray( formulas );
subclassFormulaTemplateClosure = ArrayHelper.toStringArray( formulaTemplates );
subclassFormulaAliasClosure = ArrayHelper.toStringArray( formulaAliases );
subclassFormulaLazyClosure = ArrayHelper.toBooleanArray( formulasLazy );
subclassPropertyNameClosure = ArrayHelper.toStringArray( names );
subclassPropertySubclassNameClosure = ArrayHelper.toStringArray( classes );
subclassPropertyTypeClosure = ArrayHelper.toTypeArray( types );
subclassPropertyNullabilityClosure = ArrayHelper.toBooleanArray( propNullables );
subclassPropertyFormulaTemplateClosure = ArrayHelper.to2DStringArray( templates );
subclassPropertyColumnNameClosure = ArrayHelper.to2DStringArray( propColumns );
subclassPropertyColumnReaderClosure = ArrayHelper.to2DStringArray( propColumnReaders );
subclassPropertyColumnReaderTemplateClosure = ArrayHelper.to2DStringArray( propColumnReaderTemplates );
subclassPropertyColumnNumberClosure = ArrayHelper.to2DIntArray( propColumnNumbers );
subclassPropertyFormulaNumberClosure = ArrayHelper.to2DIntArray( propFormulaNumbers );
subclassPropertyCascadeStyleClosure = cascades.toArray( new CascadeStyle[ cascades.size() ] );
subclassPropertyFetchModeClosure = joinedFetchesList.toArray( new FetchMode[ joinedFetchesList.size() ] );
propertyDefinedOnSubclass = ArrayHelper.toBooleanArray( definedBySubclass );
Map<String, String> filterDefaultConditionsByName = new HashMap<String, String>();
for ( FilterDefinition filterDefinition : entityBinding.getFilterDefinitions() ) {
filterDefaultConditionsByName.put( filterDefinition.getFilterName(), filterDefinition.getDefaultFilterCondition() );
}
filterHelper = new FilterHelper( filterDefaultConditionsByName, factory.getDialect(), factory.getSqlFunctionRegistry() );
temporaryIdTableName = null;
temporaryIdTableDDL = null;
propertyMapping = null;
}
protected static String getTemplateFromString(String string, SessionFactoryImplementor factory) {
return string == null ?
null :
Template.renderWhereStringTemplate( string, factory.getDialect(), factory.getSqlFunctionRegistry() );
}
public String getTemplateFromColumn(org.hibernate.metamodel.relational.Column column, SessionFactoryImplementor factory) {
String templateString;
if ( column.getReadFragment() != null ) {
templateString = getTemplateFromString( column.getReadFragment(), factory );
}
else {
String columnName = column.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() );
templateString = Template.TEMPLATE + '.' + columnName;
}
return templateString;
}
protected String generateLazySelectString() {
@ -1824,6 +2002,73 @@ public abstract class AbstractEntityPersister
}
/**
* Must be called by subclasses, at the end of their constructors
*/
protected void initSubclassPropertyAliasesMap(EntityBinding model) throws MappingException {
// ALIASES
// TODO: Fix when subclasses are working (HHH-6337)
//internalInitSubclassPropertyAliasesMap( null, model.getSubclassPropertyClosureIterator() );
// aliases for identifier ( alias.id ); skip if the entity defines a non-id property named 'id'
if ( ! entityMetamodel.hasNonIdentifierPropertyNamedId() ) {
subclassPropertyAliases.put( ENTITY_ID, getIdentifierAliases() );
subclassPropertyColumnNames.put( ENTITY_ID, getIdentifierColumnNames() );
}
// aliases named identifier ( alias.idname )
if ( hasIdentifierProperty() ) {
subclassPropertyAliases.put( getIdentifierPropertyName(), getIdentifierAliases() );
subclassPropertyColumnNames.put( getIdentifierPropertyName(), getIdentifierColumnNames() );
}
// aliases for composite-id's
if ( getIdentifierType().isComponentType() ) {
// Fetch embedded identifiers propertynames from the "virtual" identifier component
CompositeType componentId = ( CompositeType ) getIdentifierType();
String[] idPropertyNames = componentId.getPropertyNames();
String[] idAliases = getIdentifierAliases();
String[] idColumnNames = getIdentifierColumnNames();
for ( int i = 0; i < idPropertyNames.length; i++ ) {
if ( entityMetamodel.hasNonIdentifierPropertyNamedId() ) {
subclassPropertyAliases.put(
ENTITY_ID + "." + idPropertyNames[i],
new String[] { idAliases[i] }
);
subclassPropertyColumnNames.put(
ENTITY_ID + "." + getIdentifierPropertyName() + "." + idPropertyNames[i],
new String[] { idColumnNames[i] }
);
}
// if (hasIdentifierProperty() && !ENTITY_ID.equals( getIdentifierPropertyName() ) ) {
if ( hasIdentifierProperty() ) {
subclassPropertyAliases.put(
getIdentifierPropertyName() + "." + idPropertyNames[i],
new String[] { idAliases[i] }
);
subclassPropertyColumnNames.put(
getIdentifierPropertyName() + "." + idPropertyNames[i],
new String[] { idColumnNames[i] }
);
}
else {
// embedded composite ids ( alias.idname1, alias.idname2 )
subclassPropertyAliases.put( idPropertyNames[i], new String[] { idAliases[i] } );
subclassPropertyColumnNames.put( idPropertyNames[i], new String[] { idColumnNames[i] } );
}
}
}
if ( entityMetamodel.isPolymorphic() ) {
subclassPropertyAliases.put( ENTITY_CLASS, new String[] { getDiscriminatorAlias() } );
subclassPropertyColumnNames.put( ENTITY_CLASS, new String[] { getDiscriminatorColumnName() } );
}
}
private void internalInitSubclassPropertyAliasesMap(String path, Iterator propertyIterator) {
while ( propertyIterator.hasNext() ) {

View File

@ -47,7 +47,12 @@ import org.hibernate.mapping.Selectable;
import org.hibernate.mapping.Subclass;
import org.hibernate.mapping.Table;
import org.hibernate.mapping.Value;
import org.hibernate.metamodel.binding.AttributeBinding;
import org.hibernate.metamodel.binding.CustomSQL;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.relational.DerivedValue;
import org.hibernate.metamodel.relational.SimpleValue;
import org.hibernate.metamodel.relational.TableSpecification;
import org.hibernate.sql.InFragment;
import org.hibernate.sql.Insert;
import org.hibernate.sql.SelectFragment;
@ -120,6 +125,8 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
private static final Object NULL_DISCRIMINATOR = new MarkerObject("<null discriminator>");
private static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject("<not null discriminator>");
private static final String NULL_STRING = "null";
private static final String NOT_NULL_STRING = "not null";
//INITIALIZATION:
@ -447,39 +454,262 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
super( entityBinding, cacheAccessStrategy, factory );
//TODO: implement!!!! initializing final fields to make compiler happy...
joinSpan = -1;
qualifiedTableNames = null;
isInverseTable = null;
isNullableTable = null;
keyColumnNames = null;
cascadeDeleteEnabled = null;
hasSequentialSelects = false;
spaces = null;
subclassClosure = null;
subclassTableNameClosure = null;
subclassTableIsLazyClosure = null;
isInverseSubclassTable = null;
isNullableSubclassTable = null;
subclassTableSequentialSelect = null;
subclassTableKeyColumnClosure = null;
isClassOrSuperclassTable = null;
propertyTableNumbers = null;
subclassPropertyTableNumberClosure = null;
subclassColumnTableNumberClosure = null;
subclassFormulaTableNumberClosure = null;
forceDiscriminator = false;
// CLASS + TABLE
// TODO: fix when joins are working (HHH-6391)
//joinSpan = entityBinding.getJoinClosureSpan() + 1;
joinSpan = 1;
qualifiedTableNames = new String[joinSpan];
isInverseTable = new boolean[joinSpan];
isNullableTable = new boolean[joinSpan];
keyColumnNames = new String[joinSpan][];
// TODO: fix when EntityBinhding.getRootEntityBinding() exists (HHH-6337)
//final Table table = entityBinding.getRootEntityBinding().getBaseTable();
final TableSpecification table = entityBinding.getBaseTable();
qualifiedTableNames[0] = table.getQualifiedName( factory.getDialect() );
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];
initializeCustomSql( entityBinding.getCustomInsert(), 0, customSQLInsert, insertCallable, insertResultCheckStyles );
initializeCustomSql( entityBinding.getCustomUpdate(), 0, customSQLUpdate, updateCallable, updateResultCheckStyles );
initializeCustomSql( entityBinding.getCustomDelete(), 0, customSQLDelete, deleteCallable, deleteResultCheckStyles );
// JOINS
// TODO: add join stuff when HHH-6391 is working
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( entityBinding.getSynchronizedTableNames() )
);
final boolean lazyAvailable = isInstrumented();
boolean hasDeferred = false;
ArrayList subclassTables = new ArrayList();
ArrayList joinKeyColumns = new ArrayList();
ArrayList<Boolean> isConcretes = new ArrayList<Boolean>();
ArrayList<Boolean> isDeferreds = new ArrayList<Boolean>();
ArrayList<Boolean> isInverses = new ArrayList<Boolean>();
ArrayList<Boolean> isNullables = new ArrayList<Boolean>();
ArrayList<Boolean> isLazies = new ArrayList<Boolean>();
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);
// TODO: add join stuff when HHH-6391 is working
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
// TODO: fix this when can get subclass info from EntityBinding (HHH-6337)
// for now set hasSubclasses to false
//hasSubclasses = entityBinding.hasSubclasses();
boolean hasSubclasses = false;
//polymorphic = ! entityBinding.isRoot() || entityBinding.hasSubclasses();
boolean isPolymorphic = ! entityBinding.isRoot() || hasSubclasses;
final Object discriminatorValue;
if ( isPolymorphic ) {
org.hibernate.metamodel.relational.Value discrimValue =
entityBinding.getEntityDiscriminator().getValueBinding().getValue();
if (discrimValue==null) {
throw new MappingException("discriminator mapping required for single table polymorphic persistence");
}
forceDiscriminator = entityBinding.getEntityDiscriminator().isForced();
if ( ! SimpleValue.class.isInstance( discrimValue ) ) {
throw new MappingException( "discriminator must be mapped to a single column or formula." );
}
if ( DerivedValue.class.isInstance( discrimValue ) ) {
DerivedValue formula = ( DerivedValue ) discrimValue;
discriminatorFormula = formula.getExpression();
discriminatorFormulaTemplate = getTemplateFromString( formula.getExpression(), factory );
discriminatorColumnName = null;
discriminatorColumnReaders = null;
discriminatorColumnReaderTemplate = null;
discriminatorAlias = "clazz_";
}
else if ( org.hibernate.metamodel.relational.Column.class.isInstance( discrimValue ) ) {
org.hibernate.metamodel.relational.Column column = ( org.hibernate.metamodel.relational.Column ) discrimValue;
discriminatorColumnName = column.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() );
discriminatorColumnReaders =
column.getReadFragment() == null ?
column.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ) :
column.getReadFragment();
discriminatorColumnReaderTemplate = getTemplateFromColumn( column, factory );
// TODO: fix this when EntityBinding.getRootEntityBinding() is implemented;
// for now, assume entityBinding is the root
//discriminatorAlias = column.getAlias( factory.getDialect(), entityBinding.getRootEntityBinding().getBaseTable );
discriminatorAlias = column.getAlias( factory.getDialect() );
discriminatorFormula = null;
discriminatorFormulaTemplate = null;
}
else {
throw new MappingException( "Unknown discriminator value type:" + discrimValue.toLoggableString() );
}
discriminatorType =
entityBinding
.getEntityDiscriminator()
.getValueBinding()
.getHibernateTypeDescriptor()
.getExplicitType();
if ( entityBinding.getDiscriminatorValue() == null ) {
discriminatorValue = NULL_DISCRIMINATOR;
discriminatorSQLValue = InFragment.NULL;
discriminatorInsertable = false;
}
else if ( entityBinding.getDiscriminatorValue().equals( NULL_STRING ) ) {
discriminatorValue = NOT_NULL_DISCRIMINATOR;
discriminatorSQLValue = InFragment.NOT_NULL;
discriminatorInsertable = false;
}
else if ( entityBinding.getDiscriminatorValue().equals( NOT_NULL_STRING ) ) {
discriminatorValue = NOT_NULL_DISCRIMINATOR;
discriminatorSQLValue = InFragment.NOT_NULL;
discriminatorInsertable = false;
}
else {
discriminatorInsertable =
entityBinding.getEntityDiscriminator().isInserted() &&
! DerivedValue.class.isInstance( discrimValue );
try {
DiscriminatorType dtype = ( DiscriminatorType ) discriminatorType;
discriminatorValue = dtype.stringToObject( entityBinding.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;
discriminatorColumnReaders = null;
discriminatorColumnReaderTemplate = null;
discriminatorAlias = null;
discriminatorType = null;
discriminatorValue = null;
discriminatorSQLValue = null;
discriminatorInsertable = false;
constraintOrderedTableNames = null;
constraintOrderedKeyColumnNames = null;
discriminatorFormula = null;
discriminatorFormulaTemplate = null;
}
// PROPERTIES
propertyTableNumbers = new int[ getPropertySpan() ];
int i=0;
for( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) {
// TODO: fix when joins are working (HHH-6391)
//propertyTableNumbers[i++] = entityBinding.getJoinNumber( attributeBinding);
if ( attributeBinding == entityBinding.getEntityIdentifier().getValueBinding() ) {
continue; // skip identifier binding
}
propertyTableNumbers[ i++ ] = 0;
}
//TODO: code duplication with JoinedSubclassEntityPersister
ArrayList columnJoinNumbers = new ArrayList();
ArrayList formulaJoinedNumbers = new ArrayList();
ArrayList propertyJoinNumbers = new ArrayList();
// TODO: fix when subclasses are working (HHH-6337)
//for ( AttributeBinding prop : entityBinding.getSubclassAttributeBindingClosure() ) {
for ( AttributeBinding prop : entityBinding.getAttributeBindingClosure() ) {
// TODO: fix when joins are working (HHH-6391)
//int join = entityBinding.getJoinNumber(prop);
int join = 0;
propertyJoinNumbers.add(join);
//propertyTableNumbersByName.put( prop.getName(), join );
propertyTableNumbersByNameAndSubclass.put(
prop.getEntityBinding().getEntity().getName() + '.' + prop.getAttribute().getName(),
join
);
for ( SimpleValue simpleValue : prop.getValues() ) {
if ( DerivedValue.class.isInstance( simpleValue ) ) {
formulaJoinedNumbers.add( join );
}
else {
columnJoinNumbers.add( join );
}
}
}
subclassColumnTableNumberClosure = ArrayHelper.toIntArray(columnJoinNumbers);
subclassFormulaTableNumberClosure = ArrayHelper.toIntArray(formulaJoinedNumbers);
subclassPropertyTableNumberClosure = ArrayHelper.toIntArray(propertyJoinNumbers);
// TODO; fix when subclasses are working (HHH-6337)
//int subclassSpan = entityBinding.getSubclassSpan() + 1;
int subclassSpan = 1;
subclassClosure = new String[subclassSpan];
subclassClosure[0] = getEntityName();
if ( isPolymorphic ) {
subclassesByDiscriminatorValue.put( discriminatorValue, getEntityName() );
}
// SUBCLASSES
// TODO; fix when subclasses are working (HHH-6337)
initLockers();
initSubclassPropertyAliasesMap( entityBinding );
postConstruct( mapping );
}
private static void initializeCustomSql(
CustomSQL customSql,
int i,
String[] sqlStrings,
boolean[] callable,
ExecuteUpdateResultCheckStyle[] checkStyles) {
sqlStrings[i] = customSql != null ? customSql.getSql(): null;
callable[i] = sqlStrings[i] != null && customSql.isCallable();
checkStyles[i] = customSql != null && customSql.getCheckStyle() != null ?
customSql.getCheckStyle() :
ExecuteUpdateResultCheckStyle.determineDefault( sqlStrings[i], callable[i] );
}
protected boolean isInverseTable(int j) {