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.currentSessionContext = null;
|
||||||
this.sqlFunctionRegistry = null;
|
this.sqlFunctionRegistry = null;
|
||||||
this.transactionEnvironment = null;
|
this.transactionEnvironment = null;
|
||||||
this.jdbcServices = null;
|
|
||||||
this.dialect = null;
|
|
||||||
|
|
||||||
this.sessionFactoryOptions = sessionFactoryOptions;
|
this.sessionFactoryOptions = sessionFactoryOptions;
|
||||||
|
|
||||||
|
@ -560,6 +558,9 @@ public final class SessionFactoryImpl
|
||||||
.getService( SessionFactoryServiceRegistryFactory.class )
|
.getService( SessionFactoryServiceRegistryFactory.class )
|
||||||
.buildServiceRegistry( this, metadata );
|
.buildServiceRegistry( this, metadata );
|
||||||
|
|
||||||
|
this.jdbcServices = this.serviceRegistry.getService( JdbcServices.class );
|
||||||
|
this.dialect = this.jdbcServices.getDialect();
|
||||||
|
|
||||||
// TODO: get SQL functions from a new service
|
// TODO: get SQL functions from a new service
|
||||||
// this.sqlFunctionRegistry = new SQLFunctionRegistry( getDialect(), cfg.getSqlFunctions() );
|
// this.sqlFunctionRegistry = new SQLFunctionRegistry( getDialect(), cfg.getSqlFunctions() );
|
||||||
|
|
||||||
|
@ -754,8 +755,7 @@ public final class SessionFactoryImpl
|
||||||
Iterator iter = entityPersisters.values().iterator();
|
Iterator iter = entityPersisters.values().iterator();
|
||||||
while ( iter.hasNext() ) {
|
while ( iter.hasNext() ) {
|
||||||
final EntityPersister persister = ( ( EntityPersister ) iter.next() );
|
final EntityPersister persister = ( ( EntityPersister ) iter.next() );
|
||||||
// TODO: broken
|
persister.postInstantiate();
|
||||||
//persister.postInstantiate();
|
|
||||||
registerEntityNameResolvers( persister );
|
registerEntityNameResolvers( persister );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -959,19 +959,17 @@ public final class SessionFactoryImpl
|
||||||
}
|
}
|
||||||
|
|
||||||
public JdbcServices getJdbcServices() {
|
public JdbcServices getJdbcServices() {
|
||||||
return jdbcServices;
|
return jdbcServices;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Dialect getDialect() {
|
public Dialect getDialect() {
|
||||||
if ( serviceRegistry == null ) {
|
if ( serviceRegistry == null ) {
|
||||||
throw new IllegalStateException( "Cannot determine dialect because serviceRegistry is null." );
|
throw new IllegalStateException( "Cannot determine dialect because serviceRegistry is null." );
|
||||||
}
|
}
|
||||||
return dialect;
|
return dialect;
|
||||||
//return getJdbcServices().getDialect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Interceptor getInterceptor()
|
public Interceptor getInterceptor() {
|
||||||
{
|
|
||||||
return sessionFactoryOptions.getInterceptor();
|
return sessionFactoryOptions.getInterceptor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,10 +42,13 @@ import org.hibernate.AssertionFailure;
|
||||||
import org.hibernate.EntityMode;
|
import org.hibernate.EntityMode;
|
||||||
import org.hibernate.FetchMode;
|
import org.hibernate.FetchMode;
|
||||||
import org.hibernate.HibernateException;
|
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.internal.Versioning;
|
||||||
import org.hibernate.engine.spi.EntityEntry;
|
import org.hibernate.engine.spi.EntityEntry;
|
||||||
import org.hibernate.engine.spi.EntityKey;
|
import org.hibernate.engine.spi.EntityKey;
|
||||||
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
|
||||||
|
import org.hibernate.engine.spi.FilterDefinition;
|
||||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||||
import org.hibernate.engine.spi.Mapping;
|
import org.hibernate.engine.spi.Mapping;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
@ -92,7 +95,11 @@ import org.hibernate.mapping.PersistentClass;
|
||||||
import org.hibernate.mapping.Property;
|
import org.hibernate.mapping.Property;
|
||||||
import org.hibernate.mapping.Selectable;
|
import org.hibernate.mapping.Selectable;
|
||||||
import org.hibernate.metadata.ClassMetadata;
|
import org.hibernate.metadata.ClassMetadata;
|
||||||
|
import org.hibernate.metamodel.binding.AttributeBinding;
|
||||||
import org.hibernate.metamodel.binding.EntityBinding;
|
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.pretty.MessageHelper;
|
||||||
import org.hibernate.property.BackrefPropertyAccessor;
|
import org.hibernate.property.BackrefPropertyAccessor;
|
||||||
import org.hibernate.sql.Alias;
|
import org.hibernate.sql.Alias;
|
||||||
|
@ -771,62 +778,233 @@ public abstract class AbstractEntityPersister
|
||||||
new StructuredCacheEntry(this) :
|
new StructuredCacheEntry(this) :
|
||||||
new UnstructuredCacheEntry();
|
new UnstructuredCacheEntry();
|
||||||
this.entityMetamodel = new EntityMetamodel( entityBinding, factory );
|
this.entityMetamodel = new EntityMetamodel( entityBinding, factory );
|
||||||
rootTableKeyColumnNames = null;
|
int batch = entityBinding.getBatchSize();
|
||||||
rootTableKeyColumnReaders = null;
|
if ( batch == -1 ) {
|
||||||
rootTableKeyColumnReaderTemplates = null;
|
batch = factory.getSettings().getDefaultBatchFetchSize();
|
||||||
identifierAliases = null;
|
}
|
||||||
identifierColumnSpan = -1;
|
batchSize = batch;
|
||||||
versionColumnName = null;
|
hasSubselectLoadableCollections = entityBinding.hasSubselectLoadableCollections();
|
||||||
hasFormulaProperties = false;
|
|
||||||
batchSize = -1;
|
propertyMapping = new BasicEntityPropertyMapping( this );
|
||||||
hasSubselectLoadableCollections = false;
|
|
||||||
rowIdName = null;
|
// IDENTIFIER
|
||||||
lazyProperties = null;
|
|
||||||
sqlWhereString = null;
|
identifierColumnSpan = entityBinding.getEntityIdentifier().getValueBinding().getValuesSpan();
|
||||||
sqlWhereStringTemplate = null;
|
rootTableKeyColumnNames = new String[identifierColumnSpan];
|
||||||
propertyColumnSpans = null;
|
rootTableKeyColumnReaders = new String[identifierColumnSpan];
|
||||||
propertySubclassNames = null;
|
rootTableKeyColumnReaderTemplates = new String[identifierColumnSpan];
|
||||||
propertyColumnAliases = null;
|
identifierAliases = new String[identifierColumnSpan];
|
||||||
propertyColumnNames = null;
|
|
||||||
propertyColumnFormulaTemplates = null;
|
rowIdName = entityBinding.getRowId();
|
||||||
propertyColumnReaderTemplates = null;
|
|
||||||
propertyColumnWriters = null;
|
loaderName = entityBinding.getLoaderName();
|
||||||
propertyColumnUpdateable = null;
|
|
||||||
propertyColumnInsertable = null;
|
int i = 0;
|
||||||
propertyUniqueness = null;
|
for ( org.hibernate.metamodel.relational.Column col : entityBinding.getBaseTable().getPrimaryKey().getColumns() ) {
|
||||||
propertySelectable = null;
|
rootTableKeyColumnNames[i] = col.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() );
|
||||||
lazyPropertyNames = null;
|
if ( col.getReadFragment() == null ) {
|
||||||
lazyPropertyNumbers = null;
|
rootTableKeyColumnReaders[i] = rootTableKeyColumnNames[i];
|
||||||
lazyPropertyTypes = null;
|
rootTableKeyColumnReaderTemplates[i] = getTemplateFromColumn( col, factory );
|
||||||
lazyPropertyColumnAliases = null;
|
}
|
||||||
subclassPropertyNameClosure = null;
|
else {
|
||||||
subclassPropertySubclassNameClosure = null;
|
rootTableKeyColumnReaders[i] = col.getReadFragment();
|
||||||
subclassPropertyTypeClosure = null;
|
rootTableKeyColumnReaderTemplates[i] = getTemplateFromString( col.getReadFragment(), factory );
|
||||||
subclassPropertyFormulaTemplateClosure = null;
|
}
|
||||||
subclassPropertyColumnNameClosure = null;
|
// TODO: Fix when HHH-6337 is fixed; for now assume entityBinding is the root
|
||||||
subclassPropertyColumnReaderClosure = null;
|
// identifierAliases[i] = col.getAlias( factory.getDialect(), entityBinding.getRootEntityBinding().getBaseTable() );
|
||||||
subclassPropertyColumnReaderTemplateClosure = null;
|
identifierAliases[i] = col.getAlias( factory.getDialect() );
|
||||||
subclassPropertyFetchModeClosure = null;
|
i++;
|
||||||
subclassPropertyNullabilityClosure = null;
|
}
|
||||||
propertyDefinedOnSubclass = null;
|
|
||||||
subclassPropertyColumnNumberClosure = null;
|
// VERSION
|
||||||
subclassPropertyFormulaNumberClosure = null;
|
|
||||||
subclassPropertyCascadeStyleClosure = null;
|
if ( entityBinding.isVersioned() ) {
|
||||||
subclassColumnClosure = null;
|
// Use AttributeBinding.getValues() due to HHH-6380
|
||||||
subclassColumnLazyClosure = null;
|
Iterator<SimpleValue> valueIterator = entityBinding.getVersioningValueBinding().getValues().iterator();
|
||||||
subclassColumnAliasClosure = null;
|
SimpleValue versionValue = valueIterator.next();
|
||||||
subclassColumnSelectableClosure = null;
|
if ( ! ( versionValue instanceof org.hibernate.metamodel.relational.Column ) || valueIterator.hasNext() ) {
|
||||||
subclassColumnReaderTemplateClosure = null;
|
throw new MappingException( "Version must be a single column value." );
|
||||||
subclassFormulaClosure = null;
|
}
|
||||||
subclassFormulaTemplateClosure = null;
|
org.hibernate.metamodel.relational.Column versionColumn =
|
||||||
subclassFormulaAliasClosure = null;
|
( org.hibernate.metamodel.relational.Column ) versionValue;
|
||||||
subclassFormulaLazyClosure = null;
|
versionColumnName = versionColumn.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() );
|
||||||
filterHelper = null;
|
}
|
||||||
loaderName = null;
|
else {
|
||||||
queryLoader = null;
|
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;
|
temporaryIdTableName = null;
|
||||||
temporaryIdTableDDL = 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() {
|
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) {
|
private void internalInitSubclassPropertyAliasesMap(String path, Iterator propertyIterator) {
|
||||||
while ( propertyIterator.hasNext() ) {
|
while ( propertyIterator.hasNext() ) {
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,12 @@ import org.hibernate.mapping.Selectable;
|
||||||
import org.hibernate.mapping.Subclass;
|
import org.hibernate.mapping.Subclass;
|
||||||
import org.hibernate.mapping.Table;
|
import org.hibernate.mapping.Table;
|
||||||
import org.hibernate.mapping.Value;
|
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.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.InFragment;
|
||||||
import org.hibernate.sql.Insert;
|
import org.hibernate.sql.Insert;
|
||||||
import org.hibernate.sql.SelectFragment;
|
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 NULL_DISCRIMINATOR = new MarkerObject("<null discriminator>");
|
||||||
private static final Object NOT_NULL_DISCRIMINATOR = new MarkerObject("<not 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:
|
//INITIALIZATION:
|
||||||
|
|
||||||
|
@ -447,39 +454,262 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
||||||
|
|
||||||
super( entityBinding, cacheAccessStrategy, factory );
|
super( entityBinding, cacheAccessStrategy, factory );
|
||||||
|
|
||||||
//TODO: implement!!!! initializing final fields to make compiler happy...
|
// CLASS + TABLE
|
||||||
joinSpan = -1;
|
|
||||||
qualifiedTableNames = null;
|
// TODO: fix when joins are working (HHH-6391)
|
||||||
isInverseTable = null;
|
//joinSpan = entityBinding.getJoinClosureSpan() + 1;
|
||||||
isNullableTable = null;
|
joinSpan = 1;
|
||||||
keyColumnNames = null;
|
qualifiedTableNames = new String[joinSpan];
|
||||||
cascadeDeleteEnabled = null;
|
isInverseTable = new boolean[joinSpan];
|
||||||
hasSequentialSelects = false;
|
isNullableTable = new boolean[joinSpan];
|
||||||
spaces = null;
|
keyColumnNames = new String[joinSpan][];
|
||||||
subclassClosure = null;
|
|
||||||
subclassTableNameClosure = null;
|
// TODO: fix when EntityBinhding.getRootEntityBinding() exists (HHH-6337)
|
||||||
subclassTableIsLazyClosure = null;
|
//final Table table = entityBinding.getRootEntityBinding().getBaseTable();
|
||||||
isInverseSubclassTable = null;
|
final TableSpecification table = entityBinding.getBaseTable();
|
||||||
isNullableSubclassTable = null;
|
qualifiedTableNames[0] = table.getQualifiedName( factory.getDialect() );
|
||||||
subclassTableSequentialSelect = null;
|
isInverseTable[0] = false;
|
||||||
subclassTableKeyColumnClosure = null;
|
isNullableTable[0] = false;
|
||||||
isClassOrSuperclassTable = null;
|
keyColumnNames[0] = getIdentifierColumnNames();
|
||||||
propertyTableNumbers = null;
|
cascadeDeleteEnabled = new boolean[joinSpan];
|
||||||
subclassPropertyTableNumberClosure = null;
|
|
||||||
subclassColumnTableNumberClosure = null;
|
// Custom sql
|
||||||
subclassFormulaTableNumberClosure = null;
|
customSQLInsert = new String[joinSpan];
|
||||||
forceDiscriminator = false;
|
customSQLUpdate = new String[joinSpan];
|
||||||
discriminatorColumnName = null;
|
customSQLDelete = new String[joinSpan];
|
||||||
discriminatorColumnReaders = null;
|
insertCallable = new boolean[joinSpan];
|
||||||
discriminatorColumnReaderTemplate = null;
|
updateCallable = new boolean[joinSpan];
|
||||||
discriminatorFormula = null;
|
deleteCallable = new boolean[joinSpan];
|
||||||
discriminatorFormulaTemplate = null;
|
insertResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];
|
||||||
discriminatorAlias = null;
|
updateResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];
|
||||||
discriminatorType = null;
|
deleteResultCheckStyles = new ExecuteUpdateResultCheckStyle[joinSpan];
|
||||||
discriminatorSQLValue = null;
|
|
||||||
discriminatorInsertable = false;
|
initializeCustomSql( entityBinding.getCustomInsert(), 0, customSQLInsert, insertCallable, insertResultCheckStyles );
|
||||||
constraintOrderedTableNames = null;
|
initializeCustomSql( entityBinding.getCustomUpdate(), 0, customSQLUpdate, updateCallable, updateResultCheckStyles );
|
||||||
constraintOrderedKeyColumnNames = null;
|
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) {
|
protected boolean isInverseTable(int j) {
|
||||||
|
|
Loading…
Reference in New Issue