From e99826940248789fc384ab26ce6b26606ab91411 Mon Sep 17 00:00:00 2001 From: Strong Liu Date: Thu, 15 Nov 2012 19:54:51 +0800 Subject: [PATCH] HHH-7736 partial joined subclass support --- .../cache/spi/entry/CacheEntryStructure.java | 31 ++- .../cache/spi/entry/StructuredCacheEntry.java | 30 +-- .../entry/StructuredCollectionCacheEntry.java | 16 +- .../spi/entry/StructuredMapCacheEntry.java | 37 ++- .../spi/entry/UnstructuredCacheEntry.java | 13 +- .../util/collections/JoinedIterator.java | 18 +- .../util/collections/SingletonIterator.java | 10 +- .../hibernate/metamodel/internal/Binder.java | 250 +++++++++++------- .../metamodel/internal/MetadataImpl.java | 4 +- .../attribute/AssociationAttribute.java | 3 +- .../annotations/entity/EntityClass.java | 2 +- .../annotations/entity/RootEntityClass.java | 16 ++ .../source/annotations/util/JPADotNames.java | 2 +- .../metamodel/spi/binding/EntityBinding.java | 32 ++- .../metamodel/spi/relational/Column.java | 21 ++ .../AbstractCollectionPersister.java | 2 +- .../collection/BasicCollectionPersister.java | 16 +- .../entity/AbstractEntityPersister.java | 4 +- .../entity/JoinedSubclassEntityPersister.java | 67 +++-- .../entity/UnionSubclassEntityPersister.java | 6 +- 20 files changed, 386 insertions(+), 194 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/CacheEntryStructure.java b/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/CacheEntryStructure.java index 5bc5414846..583f578e57 100755 --- a/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/CacheEntryStructure.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/CacheEntryStructure.java @@ -26,9 +26,34 @@ package org.hibernate.cache.spi.entry; import org.hibernate.engine.spi.SessionFactoryImplementor; /** + * {@link CacheEntry} structure, used for construct / deconstruct the cache entry to different format that store in the 2LC. + * * @author Gavin King */ -public interface CacheEntryStructure { - public Object structure(Object item); - public Object destructure(Object map, SessionFactoryImplementor factory); +public interface CacheEntryStructure { + /** + * Convert the giving {@param source} to the target format of {@link T}. + *
+ * The generic type of {@link S} should be either of : + * + *
+ * + * This is called just before cache entry being stored into 2LC. + * + * @param source The raw cache entry. + * @return The target type of value that being persisted into 2LC. + */ + public T structure(S source); + + /** + * Deconstruct the {@param target} that load from 2LC to its source type of {@link S}. + * + * @param target The item that load from the 2LC. + * @param factory The SessionFactoryImplementor. + * @return The source type of cache entry. + */ + public S destructure(T target, SessionFactoryImplementor factory); } diff --git a/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/StructuredCacheEntry.java b/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/StructuredCacheEntry.java index 095f91606c..d33c6b3aad 100755 --- a/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/StructuredCacheEntry.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/StructuredCacheEntry.java @@ -33,36 +33,36 @@ import org.hibernate.persister.entity.EntityPersister; /** * @author Gavin King */ -public class StructuredCacheEntry implements CacheEntryStructure { +public class StructuredCacheEntry implements CacheEntryStructure { - private EntityPersister persister; + private final EntityPersister persister; public StructuredCacheEntry(EntityPersister persister) { this.persister = persister; } - - public Object destructure(Object item, SessionFactoryImplementor factory) { - Map map = (Map) item; - boolean lazyPropertiesUnfetched = ( (Boolean) map.get("_lazyPropertiesUnfetched") ).booleanValue(); - String subclass = (String) map.get("_subclass"); - Object version = map.get("_version"); - EntityPersister subclassPersister = factory.getEntityPersister(subclass); + + @Override + public CacheEntry destructure(Map map, SessionFactoryImplementor factory) { + boolean lazyPropertiesUnfetched = ( (Boolean) map.get( "_lazyPropertiesUnfetched" ) ).booleanValue(); + String subclass = (String) map.get( "_subclass" ); + Object version = map.get( "_version" ); + EntityPersister subclassPersister = factory.getEntityPersister( subclass ); String[] names = subclassPersister.getPropertyNames(); Serializable[] state = new Serializable[names.length]; - for ( int i=0; i + * Internally, a list that contains all collection states is stored into 2LC. + * * @author Gavin King */ -public class StructuredCollectionCacheEntry implements CacheEntryStructure { - - public Object structure(Object item) { - CollectionCacheEntry entry = (CollectionCacheEntry) item; +public class StructuredCollectionCacheEntry implements CacheEntryStructure> { + @Override + public List structure(CollectionCacheEntry entry) { return Arrays.asList( entry.getState() ); } - - public Object destructure(Object item, SessionFactoryImplementor factory) { - List list = (List) item; + @Override + public CollectionCacheEntry destructure(List list, SessionFactoryImplementor factory) { return new CollectionCacheEntry( list.toArray( new Serializable[list.size()] ) ); } diff --git a/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/StructuredMapCacheEntry.java b/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/StructuredMapCacheEntry.java index 33dabf65b5..18ef8a6331 100755 --- a/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/StructuredMapCacheEntry.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/StructuredMapCacheEntry.java @@ -31,31 +31,30 @@ import java.util.Map; import org.hibernate.engine.spi.SessionFactoryImplementor; /** + * (De)structure the map type collection attribute that is being cached into 2LC. + * * @author Gavin King */ -public class StructuredMapCacheEntry implements CacheEntryStructure { - - public Object structure(Object item) { - CollectionCacheEntry entry = (CollectionCacheEntry) item; - Serializable[] state = entry.getState(); - Map map = new HashMap(state.length); - for ( int i=0; i> { + @Override + public Map structure(CollectionCacheEntry entry) { + final Serializable[] states = entry.getState(); + final Map map = new HashMap( states.length ); + for ( final Serializable state : states ) { + map.put( state, state ); } return map; } - - public Object destructure(Object item, SessionFactoryImplementor factory) { - Map map = (Map) item; - Serializable[] state = new Serializable[ map.size()*2 ]; - int i=0; - Iterator iter = map.entrySet().iterator(); - while ( iter.hasNext() ) { - Map.Entry me = (Map.Entry) iter.next(); - state[i++] = (Serializable) me.getKey(); - state[i++] = (Serializable) me.getValue(); + + @Override + public CollectionCacheEntry destructure(Map map, SessionFactoryImplementor factory) { + Serializable[] states = new Serializable[map.size() * 2]; + int i = 0; + for ( final Serializable key : map.keySet() ) { + states[i++] = key; + states[i++] = map.get( key ); } - return new CollectionCacheEntry(state); + return new CollectionCacheEntry( states ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/UnstructuredCacheEntry.java b/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/UnstructuredCacheEntry.java index e93ad7f44f..464b32d152 100755 --- a/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/UnstructuredCacheEntry.java +++ b/hibernate-core/src/main/java/org/hibernate/cache/spi/entry/UnstructuredCacheEntry.java @@ -26,14 +26,23 @@ package org.hibernate.cache.spi.entry; import org.hibernate.engine.spi.SessionFactoryImplementor; /** + * The very simple implementation of {@code CacheEntryStructure} that doing nothing but just return what it get. + * + *
+ * + * This is used when {@link org.hibernate.cfg.AvailableSettings#USE_STRUCTURED_CACHE} is set to {@code false}. + * + * NOTE: This property is set to {@code false} by default. + * * @author Gavin King */ -public class UnstructuredCacheEntry implements CacheEntryStructure { - +public class UnstructuredCacheEntry implements CacheEntryStructure { + @Override public Object structure(Object item) { return item; } + @Override public Object destructure(Object map, SessionFactoryImplementor factory) { return map; } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/JoinedIterator.java b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/JoinedIterator.java index b7a3e02085..6f177038ef 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/JoinedIterator.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/JoinedIterator.java @@ -36,33 +36,33 @@ import java.util.List; * invoke the Iterators in sequence until all Iterators are exhausted. * */ -public class JoinedIterator implements Iterator { +public class JoinedIterator implements Iterator { private static final Iterator[] ITERATORS = {}; // wrapped iterators - private Iterator[] iterators; + private Iterator[] iterators; // index of current iterator in the wrapped iterators array private int currentIteratorIndex; // the current iterator - private Iterator currentIterator; + private Iterator currentIterator; // the last used iterator - private Iterator lastUsedIterator; + private Iterator lastUsedIterator; - public JoinedIterator(List iterators) { - this( (Iterator[]) iterators.toArray(ITERATORS) ); + public JoinedIterator(List> iterators) { + this( iterators.toArray(ITERATORS) ); } - public JoinedIterator(Iterator[] iterators) { + public JoinedIterator(Iterator[] iterators) { if( iterators==null ) throw new NullPointerException("Unexpected NULL iterators argument"); this.iterators = iterators; } - public JoinedIterator(Iterator first, Iterator second) { + public JoinedIterator(Iterator first, Iterator second) { this( new Iterator[] { first, second } ); } @@ -71,7 +71,7 @@ public class JoinedIterator implements Iterator { return currentIterator.hasNext(); } - public Object next() { + public T next() { updateCurrentIterator(); return currentIterator.next(); } diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/SingletonIterator.java b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/SingletonIterator.java index 42f9b42a63..7a09d753ab 100755 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/collections/SingletonIterator.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/collections/SingletonIterator.java @@ -29,17 +29,17 @@ import java.util.Iterator; /** * @author Gavin King */ -public final class SingletonIterator implements Iterator { +public final class SingletonIterator implements Iterator { - private Object value; + private T value; private boolean hasNext = true; public boolean hasNext() { return hasNext; } - public Object next() { - if (hasNext) { + public T next() { + if ( hasNext ) { hasNext = false; return value; } @@ -52,7 +52,7 @@ public final class SingletonIterator implements Iterator { throw new UnsupportedOperationException(); } - public SingletonIterator(Object value) { + public SingletonIterator(T value) { this.value = value; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java index eb222ecabc..cfbb40a74d 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/Binder.java @@ -54,6 +54,7 @@ import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.ReflectHelper; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.ValueHolder; +import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.metamodel.internal.HibernateTypeHelper.ReflectedCollectionJavaTypes; import org.hibernate.metamodel.spi.MetadataImplementor; import org.hibernate.metamodel.spi.binding.AbstractPluralAttributeBinding; @@ -133,6 +134,7 @@ import org.hibernate.metamodel.spi.source.PluralAttributeElementSource; import org.hibernate.metamodel.spi.source.PluralAttributeIndexSource; import org.hibernate.metamodel.spi.source.PluralAttributeKeySource; import org.hibernate.metamodel.spi.source.PluralAttributeSource; +import org.hibernate.metamodel.spi.source.PrimaryKeyJoinColumnSource; import org.hibernate.metamodel.spi.source.RelationalValueSource; import org.hibernate.metamodel.spi.source.RelationalValueSourceContainer; import org.hibernate.metamodel.spi.source.RootEntitySource; @@ -158,7 +160,7 @@ import org.jboss.logging.Logger; /** * The common binder shared between annotations and {@code hbm.xml} processing. *

- * The API consists of {@link #Binder(org.hibernate.metamodel.spi.MetadataImplementor, IdentifierGeneratorFactory)} and {@link #bindEntities(Iterable)} + * The API consists of {@link #Binder(org.hibernate.metamodel.spi.MetadataImplementor, IdentifierGeneratorFactory)} and {@link #bindEntityHierarchies} * * @author Steve Ebersole * @author Hardy Ferentschik @@ -270,7 +272,7 @@ public class Binder { private AttributeBinding attributeBinding( final String entityName, final String attributeName ) { // Check if binding has already been created - final EntityBinding entityBinding = entityBinding( entityName ); + final EntityBinding entityBinding = findOrBindingEntityBinding( entityName ); final AttributeSource attributeSource = attributeSourcesByName.get( attributeSourcesByNameKey( entityName, attributeName ) ); bindAttribute( entityBinding, attributeSource ); return entityBinding.locateAttributeBinding( attributeName ); @@ -772,21 +774,100 @@ public class Binder { typeHelper.bindJdbcDataType( resolvedType, value ); } - private EntityBinding bindEntities( final EntityHierarchy entityHierarchy ) { + private EntityBinding bindSubEntity(final EntitySource entitySource, final EntityBinding superEntityBinding) { + // Return existing binding if available + EntityBinding entityBinding = metadata.getEntityBinding( entitySource.getEntityName() ); + if ( entityBinding != null ) { + return entityBinding; + } + final LocalBindingContext bindingContext = entitySource.getLocalBindingContext(); + bindingContexts.push( bindingContext ); + try { + // Create new entity binding + entityBinding = createEntityBinding( entitySource, superEntityBinding ); + entityBinding.setMutable( entityBinding.getHierarchyDetails().getRootEntityBinding().isMutable() ); + bindPrimaryTable( entityBinding, entitySource ); + bindSubEntityPrimaryKey( entityBinding, entitySource ); + bindSecondaryTables( entityBinding, entitySource ); + bindUniqueConstraints( entityBinding, entitySource ); + bindAttributes( entityBinding, entitySource ); + bindSubEntities( entityBinding, entitySource ); + return entityBinding; + } finally { + bindingContexts.pop(); + } + } + + private void bindSubEntityPrimaryKey(final EntityBinding entityBinding, final EntitySource entitySource) { + final InheritanceType inheritanceType = entityBinding.getHierarchyDetails().getInheritanceType(); + final EntityBinding superEntityBinding = entityBinding.getSuperEntityBinding(); + if ( superEntityBinding == null ) { + throw new AssertionFailure( "super entitybinding is null " ); + } + if ( inheritanceType == InheritanceType.JOINED ) { + SubclassEntitySource subclassEntitySource = (SubclassEntitySource) entitySource; + ForeignKey fk = entityBinding.getPrimaryTable().createForeignKey( + superEntityBinding.getPrimaryTable(), + subclassEntitySource.getJoinedForeignKeyName() + ); + final List primaryKeyJoinColumnSources = subclassEntitySource.getPrimaryKeyJoinColumnSources(); + final boolean hasPrimaryKeyJoinColumns = CollectionHelper.isNotEmpty( primaryKeyJoinColumnSources ); + final List superEntityBindingPrimaryKeyColumns = superEntityBinding.getPrimaryTable().getPrimaryKey().getColumns(); + + for ( int i = 0; i < superEntityBindingPrimaryKeyColumns.size(); i++ ) { + Column superEntityBindingPrimaryKeyColumn = superEntityBindingPrimaryKeyColumns.get( i ); + PrimaryKeyJoinColumnSource primaryKeyJoinColumnSource = hasPrimaryKeyJoinColumns && i < primaryKeyJoinColumnSources + .size() ? primaryKeyJoinColumnSources.get( i ) : null; + final String columnName; + if ( primaryKeyJoinColumnSource != null && StringHelper.isNotEmpty( primaryKeyJoinColumnSource.getColumnName() ) ) { + columnName = bindingContext().getNamingStrategy().columnName( primaryKeyJoinColumnSource.getColumnName() ); + } else { + columnName = superEntityBindingPrimaryKeyColumn.getColumnName().getText(); + } + Column column = entityBinding.getPrimaryTable().locateOrCreateColumn( columnName ); + column.setCheckCondition( superEntityBindingPrimaryKeyColumn.getCheckCondition() ); + column.setComment( superEntityBindingPrimaryKeyColumn.getComment() ); + column.setDefaultValue( superEntityBindingPrimaryKeyColumn.getDefaultValue() ); + column.setIdentity( superEntityBindingPrimaryKeyColumn.isIdentity() ); + column.setNullable( superEntityBindingPrimaryKeyColumn.isNullable() ); + column.setReadFragment( superEntityBindingPrimaryKeyColumn.getReadFragment() ); + column.setWriteFragment( superEntityBindingPrimaryKeyColumn.getWriteFragment() ); + column.setUnique( superEntityBindingPrimaryKeyColumn.isUnique() ); + final String sqlType; + if(primaryKeyJoinColumnSource!=null && StringHelper.isNotEmpty( primaryKeyJoinColumnSource.getColumnDefinition() )){ + sqlType = primaryKeyJoinColumnSource.getColumnDefinition(); + } else { + sqlType = superEntityBindingPrimaryKeyColumn.getSqlType(); + } + column.setSqlType( sqlType ); + column.setSize( superEntityBindingPrimaryKeyColumn.getSize() ); + column.setJdbcDataType( superEntityBindingPrimaryKeyColumn.getJdbcDataType() ); + entityBinding.getPrimaryTable().getPrimaryKey().addColumn( column ); + //todo still need to figure out how to handle the referencedColumnName property + fk.addColumnMapping( column, superEntityBindingPrimaryKeyColumn ); + } + } + } + + /** + * Binding a single entity hierarchy. + * + * @param entityHierarchy The entity hierarchy to be binded. + * + * @return The root {@link EntityBinding} of the entity hierarchy mapping. + */ + private EntityBinding bindEntityHierarchy(final EntityHierarchy entityHierarchy) { final RootEntitySource rootEntitySource = entityHierarchy.getRootEntitySource(); // Return existing binding if available EntityBinding rootEntityBinding = metadata.getEntityBinding( rootEntitySource.getEntityName() ); if ( rootEntityBinding != null ) { return rootEntityBinding; } - // Save inheritance type and entity mode that will apply to entire hierarchy - inheritanceTypes.push( entityHierarchy.getHierarchyInheritanceType() ); - entityModes.push( rootEntitySource.getEntityMode() ); - final LocalBindingContext bindingContext = rootEntitySource.getLocalBindingContext(); - bindingContexts.push( bindingContext ); + setupBindingContext( entityHierarchy, rootEntitySource ); try { // Create root entity binding rootEntityBinding = createEntityBinding( rootEntitySource, null ); + bindPrimaryTable( rootEntityBinding, rootEntitySource ); // Create/Bind root-specific information bindIdentifier( rootEntityBinding, rootEntitySource.getIdentifierSource() ); bindSecondaryTables( rootEntityBinding, rootEntitySource ); @@ -808,14 +889,30 @@ public class Binder { bindSubEntities( rootEntityBinding, rootEntitySource ); } } finally { - bindingContexts.pop(); - inheritanceTypes.pop(); - entityModes.pop(); + cleanupBindingContext(); } return rootEntityBinding; } - public void bindEntities( final Iterable< EntityHierarchy > entityHierarchies ) { + private void cleanupBindingContext() { + bindingContexts.pop(); + inheritanceTypes.pop(); + entityModes.pop(); + } + + private void setupBindingContext(EntityHierarchy entityHierarchy, RootEntitySource rootEntitySource) { + // Save inheritance type and entity mode that will apply to entire hierarchy + inheritanceTypes.push( entityHierarchy.getHierarchyInheritanceType() ); + entityModes.push( rootEntitySource.getEntityMode() ); + bindingContexts.push( rootEntitySource.getLocalBindingContext() ); + } + + /** + * The entry point of {@linkplain Binder} class, binds all the entity hierarchy one by one. + * + * @param entityHierarchies The entity hierarchies resolved from mappings + */ + public void bindEntityHierarchies(final Iterable entityHierarchies) { entitySourcesByName.clear(); attributeSourcesByName.clear(); inheritanceTypes.clear(); @@ -829,29 +926,7 @@ public class Binder { } // Bind each entity hierarchy for ( final EntityHierarchy entityHierarchy : entityHierarchies ) { - bindEntities( entityHierarchy ); - } - } - - private EntityBinding bindEntity( final EntitySource entitySource, final EntityBinding superEntityBinding ) { - // Return existing binding if available - EntityBinding entityBinding = metadata.getEntityBinding( entitySource.getEntityName() ); - if ( entityBinding != null ) { - return entityBinding; - } - final LocalBindingContext bindingContext = entitySource.getLocalBindingContext(); - bindingContexts.push( bindingContext ); - try { - // Create new entity binding - entityBinding = createEntityBinding( entitySource, superEntityBinding ); - entityBinding.setMutable( entityBinding.getHierarchyDetails().getRootEntityBinding().isMutable() ); - bindSecondaryTables( entityBinding, entitySource ); - bindUniqueConstraints( entityBinding, entitySource ); - bindAttributes( entityBinding, entitySource ); - bindSubEntities( entityBinding, entitySource ); - return entityBinding; - } finally { - bindingContexts.pop(); + bindEntityHierarchy( entityHierarchy ); } } @@ -1122,7 +1197,7 @@ public class Binder { bindingContext().qualifyClassName( attributeSource.getReferencedEntityName() != null ? attributeSource.getReferencedEntityName() : referencedJavaTypeValue.getValue().getName() ); - final EntityBinding referencedEntityBinding = entityBinding( referencedEntityName ); + final EntityBinding referencedEntityBinding = findOrBindingEntityBinding( referencedEntityName ); //now find the referenced attribute binding, either the referenced entity's id attribute or the referenced attribute //todo referenced entityBinding null check? // Foreign key... @@ -1528,7 +1603,7 @@ public class Binder { createAttributePath( attributeBinding ) ) ); } - EntityBinding referencedEntityBinding = entityBinding( referencedEntityName ); + EntityBinding referencedEntityBinding = findOrBindingEntityBinding( referencedEntityName ); bindOneToManyCollectionKey( attributeBinding, attributeSource, referencedEntityBinding ); bindOneToManyCollectionElement( (OneToManyPluralAttributeElementBinding) attributeBinding.getPluralAttributeElementBinding(), @@ -1563,21 +1638,37 @@ public class Binder { return attributeBinding; } - private void bindPrimaryTable( final EntityBinding entityBinding, final EntitySource entitySource ) { - final TableSpecification table = createTable( - entitySource.getPrimaryTable(), new DefaultNamingStrategy() { - - @Override - public String defaultName() { - String name = StringHelper.isNotEmpty( entityBinding.getJpaEntityName() ) ? entityBinding.getJpaEntityName() : entityBinding - .getEntity() - .getClassName(); - return bindingContexts.peek().getNamingStrategy().classToTableName( name ); - } + private void bindPrimaryTable(final EntityBinding entityBinding, final EntitySource entitySource) { + final EntityBinding superEntityBinding = entityBinding.getSuperEntityBinding(); + final InheritanceType inheritanceType = entityBinding.getHierarchyDetails().getInheritanceType(); + final TableSpecification table; + final String tableName; + if ( superEntityBinding != null && inheritanceType == InheritanceType.SINGLE_TABLE ) { + table = superEntityBinding.getPrimaryTable(); + tableName = superEntityBinding.getPrimaryTableName(); + // Configure discriminator if present + final String discriminatorValue = entitySource.getDiscriminatorMatchValue() != null ? + entitySource.getDiscriminatorMatchValue() + : entitySource.getEntityName(); + entityBinding.setDiscriminatorMatchValue( discriminatorValue ); + } + else { + table = createTable( + entitySource.getPrimaryTable(), new DefaultNamingStrategy() { + + @Override + public String defaultName() { + String name = StringHelper.isNotEmpty( entityBinding.getJpaEntityName() ) ? entityBinding.getJpaEntityName() : entityBinding + .getEntity() + .getClassName(); + return bindingContexts.peek().getNamingStrategy().classToTableName( name ); + } + } + ); + tableName = table.getLogicalName().getText(); } - ); entityBinding.setPrimaryTable( table ); - entityBinding.setPrimaryTableName( table.getLogicalName().getText() ); + entityBinding.setPrimaryTableName( tableName ); } private void bindSecondaryTables( final EntityBinding entityBinding, final EntitySource entitySource ) { @@ -1727,7 +1818,7 @@ public class Binder { private void bindSubEntities( final EntityBinding entityBinding, final EntitySource entitySource ) { for ( final SubclassEntitySource subEntitySource : entitySource.subclassEntitySources() ) { - bindEntity( subEntitySource, entityBinding ); + bindSubEntity( subEntitySource, entityBinding ); } } @@ -1954,6 +2045,7 @@ public class Binder { entityClassName, bindingContext.makeClassReference( entityClassName ), superEntityBinding == null ? null : superEntityBinding.getEntity() ) ); + entityBinding.setEntityName( entitySource.getEntityName() ); entityBinding.setJpaEntityName( entitySource.getJpaEntityName() ); //must before creating primary table entityBinding.setDynamicUpdate( entitySource.isDynamicUpdate() ); @@ -1961,39 +2053,11 @@ public class Binder { entityBinding.setBatchSize( entitySource.getBatchSize() ); entityBinding.setSelectBeforeUpdate( entitySource.isSelectBeforeUpdate() ); entityBinding.setAbstract( entitySource.isAbstract() ); - entityBinding.setCustomLoaderName( entitySource.getCustomLoaderName() ); entityBinding.setCustomInsert( entitySource.getCustomSqlInsert() ); entityBinding.setCustomUpdate( entitySource.getCustomSqlUpdate() ); entityBinding.setCustomDelete( entitySource.getCustomSqlDelete() ); entityBinding.setJpaCallbackClasses( entitySource.getJpaCallbackClasses() ); - // Create relational table - if ( superEntityBinding != null && inheritanceType == InheritanceType.SINGLE_TABLE ) { - entityBinding.setPrimaryTable( superEntityBinding.getPrimaryTable() ); - entityBinding.setPrimaryTableName( superEntityBinding.getPrimaryTableName() ); - // Configure discriminator if present - final String discriminatorValue = entitySource.getDiscriminatorMatchValue(); - if ( discriminatorValue != null ) { - entityBinding.setDiscriminatorMatchValue( discriminatorValue ); - } - else { - entityBinding.setDiscriminatorMatchValue( entitySource.getEntityName() ); - } - } - else { - bindPrimaryTable( entityBinding, entitySource ); - } - - if ( inheritanceType == InheritanceType.JOINED && superEntityBinding != null ) { - ForeignKey fk = entityBinding.getPrimaryTable().createForeignKey( - superEntityBinding.getPrimaryTable(), - ( (SubclassEntitySource) entitySource ).getJoinedForeignKeyName() - ); - // explicitly maps to target table pk - for ( Column column : entityBinding.getPrimaryTable().getPrimaryKey().getColumns() ) { - fk.addColumn( column ); - } - } // todo: deal with joined and unioned subclass bindings // todo: bind fetch profiles @@ -2313,27 +2377,33 @@ public class Binder { :referencedEntityBinding.locateAttributeBinding( resolutionDelegate.getJoinColumns( resolutionContext ) ); } - private EntityBinding entityBinding( final String entityName ) { + /** + * + * @param entityName + * @return + */ + private EntityBinding findOrBindingEntityBinding(final String entityName) { // Check if binding has already been created EntityBinding entityBinding = metadata.getEntityBinding( entityName ); if ( entityBinding == null ) { // Find appropriate source to create binding final EntitySource entitySource = entitySourcesByName.get( entityName ); - if(entitySource == null) { + if ( entitySource == null ) { String msg = log.missingEntitySource( entityName ); bindingContext().makeMappingException( msg ); } // Get super entity binding (creating it if necessary using recursive call to this method) - final EntityBinding superEntityBinding = - SubclassEntitySource.class.isInstance( entitySource ) - ? entityBinding( ( ( SubclassEntitySource ) entitySource ).superclassEntitySource().getEntityName() ) - : null; - // Create entity binding - entityBinding = - superEntityBinding == null - ? bindEntities( entityHierarchiesByRootEntitySource.get( entitySource ) ) - : bindEntity( entitySource, superEntityBinding ); + if ( SubclassEntitySource.class.isInstance( entitySource ) ) { + String superEntityName = ( (SubclassEntitySource) entitySource ).superclassEntitySource() + .getEntityName(); + EntityBinding superEntityBinding = findOrBindingEntityBinding( superEntityName ); + entityBinding = bindSubEntity( entitySource, superEntityBinding ); + } + else { + EntityHierarchy entityHierarchy = entityHierarchiesByRootEntitySource.get( entitySource ); + entityBinding = bindEntityHierarchy( entityHierarchy ); + } } return entityBinding; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java index b4a34b39d4..8f54089063 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/MetadataImpl.java @@ -211,7 +211,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable { } final HbmMetadataSourceProcessorImpl processor = new HbmMetadataSourceProcessorImpl( this, jaxbRoots ); final Binder binder = new Binder( this, identifierGeneratorFactory ); - binder.bindEntities( processor.extractEntityHierarchies() ); + binder.bindEntityHierarchies( processor.extractEntityHierarchies() ); } @@ -350,7 +350,7 @@ public class MetadataImpl implements MetadataImplementor, Serializable { private void processMappings(MetadataSourceProcessor[] metadataSourceProcessors) { final Binder binder = new Binder( this, identifierGeneratorFactory ); for ( MetadataSourceProcessor processor : metadataSourceProcessors ) { - binder.bindEntities( processor.extractEntityHierarchies() ); + binder.bindEntityHierarchies( processor.extractEntityHierarchies() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AssociationAttribute.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AssociationAttribute.java index 096cdf78bb..1e06fbb13f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AssociationAttribute.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/attribute/AssociationAttribute.java @@ -473,7 +473,8 @@ public class AssociationAttribute extends MappedAttribute { if ( joinTableAnnotation != null ) { if ( JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_ONE ) == null && JandexHelper.getSingleAnnotation( annotations, JPADotNames.ONE_TO_MANY ) == null - && JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_MANY ) == null ) { + && JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_MANY ) == null + && JandexHelper.getSingleAnnotation( annotations, JPADotNames.MANY_TO_ONE ) == null ) { String msg = coreLogger.joinTableForNonAssociationAttribute( getContext().getOrigin().getName(), getName() diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EntityClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EntityClass.java index e20e184af7..2bd72b3f7c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EntityClass.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/EntityClass.java @@ -262,7 +262,7 @@ public class EntityClass extends ConfiguredClass { return JandexHelper.getValue( jpaEntityAnnotation, "name", String.class ); } - private List determinPrimaryKeyJoinColumns() { + protected List determinPrimaryKeyJoinColumns() { if ( inheritanceType != InheritanceType.JOINED ) { return null; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/RootEntityClass.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/RootEntityClass.java index 317ef33db8..42c2c49d90 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/RootEntityClass.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/entity/RootEntityClass.java @@ -32,9 +32,12 @@ import javax.persistence.DiscriminatorType; import org.jboss.jandex.AnnotationInstance; import org.jboss.jandex.ClassInfo; import org.jboss.jandex.DotName; +import org.jboss.logging.Logger; import org.hibernate.AnnotationException; import org.hibernate.MappingException; +import org.hibernate.internal.CoreMessageLogger; +import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.metamodel.internal.source.annotations.AnnotationBindingContext; import org.hibernate.metamodel.internal.source.annotations.attribute.BasicAttribute; import org.hibernate.metamodel.internal.source.annotations.attribute.Column; @@ -43,6 +46,7 @@ import org.hibernate.metamodel.internal.source.annotations.util.HibernateDotName import org.hibernate.metamodel.internal.source.annotations.util.JPADotNames; import org.hibernate.metamodel.internal.source.annotations.util.JandexHelper; import org.hibernate.metamodel.spi.binding.InheritanceType; +import org.hibernate.metamodel.spi.source.PrimaryKeyJoinColumnSource; /** * Represents an root entity configured via annotations/orm-xml. @@ -51,6 +55,10 @@ import org.hibernate.metamodel.spi.binding.InheritanceType; * @author Brett Meyer */ public class RootEntityClass extends EntityClass { + private static final CoreMessageLogger LOG = Logger.getMessageLogger( + CoreMessageLogger.class, + RootEntityClass.class.getName() + ); private final IdType idType; private final List mappedSuperclasses; @@ -132,6 +140,14 @@ public class RootEntityClass extends EntityClass { return isDiscriminatorIncludedInSql; } + protected List determinPrimaryKeyJoinColumns() { + List results = super.determinPrimaryKeyJoinColumns(); + if ( CollectionHelper.isNotEmpty( results ) ) { + LOG.invalidPrimaryKeyJoinColumnAnnotation(); + } + return null; + } + @Override public Collection getSimpleAttributes() { List attributes = new ArrayList(); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/JPADotNames.java b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/JPADotNames.java index 79994cbf6d..d3d0409e38 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/JPADotNames.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/internal/source/annotations/util/JPADotNames.java @@ -153,9 +153,9 @@ public interface JPADotNames { DotName GENERATED_VALUE = DotName.createSimple( GeneratedValue.class.getName() ); DotName ID = DotName.createSimple( Id.class.getName() ); DotName ID_CLASS = DotName.createSimple( IdClass.class.getName() ); + DotName INHERITANCE = DotName.createSimple( Inheritance.class.getName() ); DotName INHERITANCE_TYPE = DotName.createSimple( InheritanceType.class.getName() ); DotName JOIN_COLUMN = DotName.createSimple( JoinColumn.class.getName() ); - DotName INHERITANCE = DotName.createSimple( Inheritance.class.getName() ); DotName JOIN_COLUMNS = DotName.createSimple( JoinColumns.class.getName() ); DotName JOIN_TABLE = DotName.createSimple( JoinTable.class.getName() ); DotName LOB = DotName.createSimple( Lob.class.getName() ); diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java index e9ab95e43b..a91e23b573 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/binding/EntityBinding.java @@ -26,6 +26,7 @@ package org.hibernate.metamodel.spi.binding; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -35,6 +36,9 @@ import org.hibernate.EntityMode; import org.hibernate.engine.spi.FilterDefinition; import org.hibernate.internal.util.ValueHolder; import org.hibernate.internal.util.collections.JoinedIterable; +import org.hibernate.internal.util.collections.JoinedIterator; +import org.hibernate.internal.util.collections.SingletonIterator; +import org.hibernate.mapping.PropertyGeneration; import org.hibernate.metamodel.spi.domain.AttributeContainer; import org.hibernate.metamodel.spi.domain.Entity; import org.hibernate.metamodel.spi.domain.SingularAttribute; @@ -102,7 +106,8 @@ public class EntityBinding extends AbstractAttributeBindingContainer { private Map attributeBindingMap = new HashMap(); private List jpaCallbackClasses = new ArrayList(); - + private final int subEntityBindingId; + private int nextSubEntityBindingId = 0; /** * Used to instantiate the EntityBinding for an entity that is the root of an inheritance hierarchy * @@ -112,6 +117,7 @@ public class EntityBinding extends AbstractAttributeBindingContainer { public EntityBinding(InheritanceType inheritanceType, EntityMode entityMode) { this.superEntityBinding = null; this.hierarchyDetails = new HierarchyDetails( this, inheritanceType, entityMode ); + this.subEntityBindingId = 0; } /** @@ -123,6 +129,11 @@ public class EntityBinding extends AbstractAttributeBindingContainer { this.superEntityBinding = superEntityBinding; this.superEntityBinding.subEntityBindings.add( this ); this.hierarchyDetails = superEntityBinding.getHierarchyDetails(); + this.subEntityBindingId = superEntityBinding.nextSubEntityBindingId(); + } + + private int nextSubEntityBindingId(){ + return ++nextSubEntityBindingId; } public HierarchyDetails getHierarchyDetails() { @@ -133,6 +144,10 @@ public class EntityBinding extends AbstractAttributeBindingContainer { return superEntityBinding; } + public int getSubEntityBindingId() { + return subEntityBindingId; + } + public boolean isRoot() { return superEntityBinding == null; } @@ -578,6 +593,21 @@ public class EntityBinding extends AbstractAttributeBindingContainer { return new JoinedIterable( iterables ); } + public Iterator getTableClosureIterator() { + if ( superEntityBinding == null ) { + return new SingletonIterator( getPrimaryTable() ); + } + else { + return new JoinedIterator( + superEntityBinding.getTableClosureIterator(), + new SingletonIterator( getPrimaryTable() ) + ); + } + } + public Iterator getKeyClosureIterator(){ + return null; + } + public void setJpaCallbackClasses(List jpaCallbackClasses) { this.jpaCallbackClasses = jpaCallbackClasses; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java index b79293a400..38263ba085 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/spi/relational/Column.java @@ -25,7 +25,9 @@ package org.hibernate.metamodel.spi.relational; import org.hibernate.MappingException; import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.function.SQLFunctionRegistry; import org.hibernate.internal.util.StringHelper; +import org.hibernate.sql.Template; /** * Models a physical column @@ -128,6 +130,25 @@ public class Column extends AbstractValue { this.comment = comment; } + public String getTemplate(Dialect dialect, SQLFunctionRegistry functionRegistry) { + return hasCustomRead() + ? Template.renderWhereStringTemplate( readFragment, dialect, functionRegistry ) + : Template.TEMPLATE + '.' + getColumnName().getText( dialect ); + } + + public boolean hasCustomRead() { + return StringHelper.isNotEmpty( readFragment ); + } + + public String getReadExpr(Dialect dialect) { + return hasCustomRead() ? readFragment : getColumnName().getText( dialect ); + } + + public String getWriteExpr() { + return StringHelper.isNotEmpty( writeFragment ) ? writeFragment : "?"; + } + + public Size getSize() { return size; } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java index f11d660fa5..b64a7633bb 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/AbstractCollectionPersister.java @@ -2140,7 +2140,7 @@ public abstract class AbstractCollectionPersister } } - + @Override public int getSize(Serializable key, SessionImplementor session) { try { PreparedStatement st = session.getTransactionCoordinator() diff --git a/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java index 2a292b0c71..3dfafd9b73 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/collection/BasicCollectionPersister.java @@ -186,16 +186,16 @@ public class BasicCollectionPersister extends AbstractCollectionPersister { return delete.toStatementString(); } - + @Override public boolean consumesEntityAlias() { return false; } - + @Override public boolean consumesCollectionAlias() { // return !isOneToMany(); return true; } - + @Override public boolean isOneToMany() { return false; } @@ -210,8 +210,10 @@ public class BasicCollectionPersister extends AbstractCollectionPersister { @Override protected int doUpdateRows(Serializable id, PersistentCollection collection, SessionImplementor session) throws HibernateException { - - if ( ArrayHelper.isAllFalse(elementColumnIsSettable) ) return 0; + + if ( ArrayHelper.isAllFalse( elementColumnIsSettable ) ) { + return 0; + } try { PreparedStatement st = null; @@ -342,11 +344,11 @@ public class BasicCollectionPersister extends AbstractCollectionPersister { throws MappingException { return BatchingCollectionInitializer.createBatchingCollectionInitializer( this, batchSize, getFactory(), loadQueryInfluencers ); } - + @Override public String fromJoinFragment(String alias, boolean innerJoin, boolean includeSubclasses) { return ""; } - + @Override public String whereJoinFragment(String alias, boolean innerJoin, boolean includeSubclasses) { return ""; } diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 7833e682ae..de6fee5548 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -507,8 +507,8 @@ public abstract class AbstractEntityPersister this.naturalIdRegionAccessStrategy = naturalIdRegionAccessStrategy; isLazyPropertiesCacheable = persistentClass.isLazyPropertiesCacheable(); this.cacheEntryStructure = factory.getSettings().isStructuredCacheEntriesEnabled() ? - (CacheEntryStructure) new StructuredCacheEntry(this) : - (CacheEntryStructure) new UnstructuredCacheEntry(); + new StructuredCacheEntry(this) : + new UnstructuredCacheEntry(); this.entityMetamodel = new EntityMetamodel( persistentClass, factory ); this.entityTuplizer = this.entityMetamodel.getTuplizer(); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java index 694b862a62..e5c8bc9a35 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/JoinedSubclassEntityPersister.java @@ -53,6 +53,8 @@ import org.hibernate.mapping.Table; import org.hibernate.metamodel.spi.binding.EntityBinding; import org.hibernate.metamodel.spi.binding.EntityDiscriminator; import org.hibernate.metamodel.spi.relational.DerivedValue; +import org.hibernate.metamodel.spi.relational.PrimaryKey; +import org.hibernate.metamodel.spi.relational.TableSpecification; import org.hibernate.sql.CaseFragment; import org.hibernate.sql.SelectFragment; import org.hibernate.type.*; @@ -517,20 +519,10 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { super( entityBinding, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory ); // DISCRIMINATOR if ( entityBinding.isPolymorphic() ) { - EntityDiscriminator discriminator = entityBinding.getHierarchyDetails().getEntityDiscriminator(); - discriminator.getRelationalValue(); - Type discriminatorType = discriminator - .getExplicitHibernateTypeDescriptor() - .getResolvedTypeMapping(); - try { - org.hibernate.type.DiscriminatorType dtype = (org.hibernate.type.DiscriminatorType) discriminatorType; - discriminatorValue = dtype.stringToObject( entityBinding.getDiscriminatorMatchValue() ); - discriminatorSQLString = dtype.objectToSQLString( discriminatorValue, factory.getDialect() ); - } - catch ( ClassCastException cce ) { - throw new MappingException( "Illegal discriminator type: " + discriminatorType.getName() ); - } - catch ( Exception e ) { + try{ + discriminatorValue = entityBinding.getSubEntityBindingId(); + discriminatorSQLString = discriminatorValue.toString(); + } catch ( Exception e ){ throw new MappingException( "Could not format discriminator value to SQL string", e ); } } @@ -546,27 +538,54 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { final int idColumnSpan = getIdentifierColumnSpan(); - ArrayList tables = new ArrayList(); + ArrayList tables = new ArrayList(); ArrayList keyColumns = new ArrayList(); ArrayList keyColumnReaders = new ArrayList(); ArrayList keyColumnReaderTemplates = new ArrayList(); ArrayList cascadeDeletes = new ArrayList(); -// Iterator titer = persistentClass.getTableClosureIterator(); -// Iterator kiter = persistentClass.getKeyClosureIterator(); - + Iterator titer = entityBinding.getTableClosureIterator(); + while ( titer.hasNext() ){ + TableSpecification table = titer.next(); + String tableName = table.getLogicalName().getText(factory.getDialect()); + tables.add( tableName ); + String[] keyCols = new String[idColumnSpan]; + String[] keyColReaders = new String[idColumnSpan]; + String[] keyColReaderTemplates = new String[idColumnSpan]; + PrimaryKey primaryKey= table.getPrimaryKey(); + for ( int k = 0; k < idColumnSpan; k++ ) { + org.hibernate.metamodel.spi.relational.Column column = primaryKey.getColumns().get( k ); + keyCols[k] = column.getColumnName().getText(factory.getDialect()); + keyColReaders[k] = column.getReadExpr( factory.getDialect() ); + keyColReaderTemplates[k] = column.getTemplate( factory.getDialect(), factory.getSqlFunctionRegistry() ); + } + keyColumns.add( keyCols ); + keyColumnReaders.add( keyColReaders ); + keyColumnReaderTemplates.add( keyColReaderTemplates ); + cascadeDeletes.add( false && factory.getDialect().supportsCascadeDelete() ); //todo add @OnDelete support + } + //Span of the tables directly mapped by this entity and super-classes, if any + coreTableSpan = tables.size(); + //todo secondary table + isNullableTable = new boolean[]{true}; + naturalOrderTableNames = ArrayHelper.toStringArray( tables ); + naturalOrderTableKeyColumns = ArrayHelper.to2DStringArray( keyColumns ); + naturalOrderTableKeyColumnReaders = ArrayHelper.to2DStringArray( keyColumnReaders ); + naturalOrderTableKeyColumnReaderTemplates = ArrayHelper.to2DStringArray( keyColumnReaderTemplates ); + naturalOrderCascadeDeleteEnabled = ArrayHelper.toBooleanArray( cascadeDeletes ); + ArrayList subtables = new ArrayList(); + ArrayList isConcretes = new ArrayList(); + ArrayList isDeferreds = new ArrayList(); + ArrayList isLazies = new ArrayList(); + keyColumns = new ArrayList(); + //todo add sub class tables here //---------------------------------------------- tableSpan = -1; tableNames = null; - naturalOrderTableNames = null; tableKeyColumns = null; tableKeyColumnReaders = null; tableKeyColumnReaderTemplates = null; - naturalOrderTableKeyColumns = null; - naturalOrderTableKeyColumnReaders = null; - naturalOrderTableKeyColumnReaderTemplates = null; - naturalOrderCascadeDeleteEnabled = null; spaces = null; subclassClosure = null; subclassTableNameClosure = null; @@ -584,8 +603,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister { notNullColumnTableNumbers = null; constraintOrderedTableNames = null; constraintOrderedKeyColumnNames = null; - coreTableSpan = -1; - isNullableTable = null; //----------------------------- initLockers(); initSubclassPropertyAliasesMap( entityBinding ); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java index 6516aa808f..8ae23845b9 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/UnionSubclassEntityPersister.java @@ -75,7 +75,7 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister { private final String[] subclassSpaces; private final Object discriminatorValue; private final String discriminatorSQLValue; - private final Map subclassByDiscriminatorValue = new HashMap(); + private final Map subclassByDiscriminatorValue = new HashMap(); private final String[] constraintOrderedTableNames; private final String[][] constraintOrderedKeyColumnNames; @@ -185,7 +185,7 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister { spaces[i] = (String) iter.next(); } - HashSet subclassTables = new HashSet(); + HashSet subclassTables = new HashSet(); iter = persistentClass.getSubclassTableClosureIterator(); while ( iter.hasNext() ) { Table table = (Table) iter.next(); @@ -251,7 +251,7 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister { super(entityBinding, cacheAccessStrategy, naturalIdRegionAccessStrategy, factory ); // TODO: implement!!! initializing final fields to null to make compiler happy. subquery = null; - tableName = null; + tableName = entityBinding.getPrimaryTable().getQualifiedName( factory.getDialect() ); subclassClosure = null; spaces = null; subclassSpaces = null;