HHH-6411 : Integrate new metamodel into SingleTableEntityPersister
This commit is contained in:
parent
d981f54942
commit
5457b6c707
|
@ -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 );
|
||||
|
||||
}
|
||||
|
@ -959,19 +959,17 @@ public final class SessionFactoryImpl
|
|||
}
|
||||
|
||||
public JdbcServices getJdbcServices() {
|
||||
return jdbcServices;
|
||||
return jdbcServices;
|
||||
}
|
||||
|
||||
public Dialect getDialect() {
|
||||
if ( serviceRegistry == null ) {
|
||||
throw new IllegalStateException( "Cannot determine dialect because serviceRegistry is null." );
|
||||
}
|
||||
return dialect;
|
||||
//return getJdbcServices().getDialect();
|
||||
return dialect;
|
||||
}
|
||||
|
||||
public Interceptor getInterceptor()
|
||||
{
|
||||
public Interceptor getInterceptor() {
|
||||
return sessionFactoryOptions.getInterceptor();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
//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() ) {
|
||||
|
||||
|
|
|
@ -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;
|
||||
discriminatorColumnName = null;
|
||||
discriminatorColumnReaders = null;
|
||||
discriminatorColumnReaderTemplate = null;
|
||||
discriminatorFormula = null;
|
||||
discriminatorFormulaTemplate = null;
|
||||
discriminatorAlias = null;
|
||||
discriminatorType = null;
|
||||
discriminatorSQLValue = null;
|
||||
discriminatorInsertable = false;
|
||||
constraintOrderedTableNames = null;
|
||||
constraintOrderedKeyColumnNames = null;
|
||||
// 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;
|
||||
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) {
|
||||
|
|
Loading…
Reference in New Issue