HHH-7736 partial joined subclass support
This commit is contained in:
parent
4359b9971b
commit
e998269402
|
@ -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<S,T> {
|
||||
/**
|
||||
* Convert the giving {@param source} to the target format of {@link T}.
|
||||
* <br>
|
||||
* The generic type of {@link S} should be either of :
|
||||
* <ul>
|
||||
* <li>{@link CacheEntry}</li>
|
||||
* <li>{@link CollectionCacheEntry}</li>
|
||||
* </ul>
|
||||
* </br>
|
||||
*
|
||||
* 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);
|
||||
}
|
||||
|
|
|
@ -33,36 +33,36 @@ import org.hibernate.persister.entity.EntityPersister;
|
|||
/**
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class StructuredCacheEntry implements CacheEntryStructure {
|
||||
public class StructuredCacheEntry implements CacheEntryStructure<CacheEntry, Map> {
|
||||
|
||||
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<names.length; i++ ) {
|
||||
for ( int i = 0; i < names.length; i++ ) {
|
||||
state[i] = (Serializable) map.get( names[i] );
|
||||
}
|
||||
return new CacheEntry(state, subclass, lazyPropertiesUnfetched, version);
|
||||
return new CacheEntry( state, subclass, lazyPropertiesUnfetched, version );
|
||||
}
|
||||
|
||||
public Object structure(Object item) {
|
||||
CacheEntry entry = (CacheEntry) item;
|
||||
@Override
|
||||
public Map structure(CacheEntry entry) {
|
||||
String[] names = persister.getPropertyNames();
|
||||
Map map = new HashMap(names.length+2);
|
||||
Map map = new HashMap( names.length + 3 );
|
||||
map.put( "_subclass", entry.getSubclass() );
|
||||
map.put( "_version", entry.getVersion() );
|
||||
map.put( "_lazyPropertiesUnfetched", entry.areLazyPropertiesUnfetched() );
|
||||
for ( int i=0; i<names.length; i++ ) {
|
||||
for ( int i = 0; i < names.length; i++ ) {
|
||||
map.put( names[i], entry.getDisassembledState()[i] );
|
||||
}
|
||||
return map;
|
||||
|
|
|
@ -30,17 +30,19 @@ import java.util.List;
|
|||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
||||
/**
|
||||
* For other plural attributes except map, this impl is used.
|
||||
* </br>
|
||||
* 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<CollectionCacheEntry, List<Serializable>> {
|
||||
@Override
|
||||
public List<Serializable> structure(CollectionCacheEntry entry) {
|
||||
return Arrays.asList( entry.getState() );
|
||||
}
|
||||
|
||||
public Object destructure(Object item, SessionFactoryImplementor factory) {
|
||||
List list = (List) item;
|
||||
@Override
|
||||
public CollectionCacheEntry destructure(List<Serializable> list, SessionFactoryImplementor factory) {
|
||||
return new CollectionCacheEntry( list.toArray( new Serializable[list.size()] ) );
|
||||
}
|
||||
|
||||
|
|
|
@ -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<state.length; ) {
|
||||
map.put( state[i++], state[i++] );
|
||||
public class StructuredMapCacheEntry implements CacheEntryStructure<CollectionCacheEntry, Map<Serializable,Serializable>> {
|
||||
@Override
|
||||
public Map<Serializable, Serializable> structure(CollectionCacheEntry entry) {
|
||||
final Serializable[] states = entry.getState();
|
||||
final Map<Serializable, Serializable> map = new HashMap<Serializable, Serializable>( 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<Serializable, Serializable> 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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* </br>
|
||||
*
|
||||
* 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<Object, Object> {
|
||||
@Override
|
||||
public Object structure(Object item) {
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object destructure(Object map, SessionFactoryImplementor factory) {
|
||||
return map;
|
||||
}
|
||||
|
|
|
@ -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<T> implements Iterator<T> {
|
||||
|
||||
private static final Iterator[] ITERATORS = {};
|
||||
|
||||
// wrapped iterators
|
||||
private Iterator[] iterators;
|
||||
private Iterator<T>[] iterators;
|
||||
|
||||
// index of current iterator in the wrapped iterators array
|
||||
private int currentIteratorIndex;
|
||||
|
||||
// the current iterator
|
||||
private Iterator currentIterator;
|
||||
private Iterator<T> currentIterator;
|
||||
|
||||
// the last used iterator
|
||||
private Iterator lastUsedIterator;
|
||||
private Iterator<T> lastUsedIterator;
|
||||
|
||||
public JoinedIterator(List iterators) {
|
||||
this( (Iterator[]) iterators.toArray(ITERATORS) );
|
||||
public JoinedIterator(List<Iterator<T>> iterators) {
|
||||
this( iterators.toArray(ITERATORS) );
|
||||
}
|
||||
|
||||
public JoinedIterator(Iterator[] iterators) {
|
||||
public JoinedIterator(Iterator<T>[] iterators) {
|
||||
if( iterators==null )
|
||||
throw new NullPointerException("Unexpected NULL iterators argument");
|
||||
this.iterators = iterators;
|
||||
}
|
||||
|
||||
public JoinedIterator(Iterator first, Iterator second) {
|
||||
public JoinedIterator(Iterator<T> first, Iterator<T> 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();
|
||||
}
|
||||
|
|
|
@ -29,17 +29,17 @@ import java.util.Iterator;
|
|||
/**
|
||||
* @author Gavin King
|
||||
*/
|
||||
public final class SingletonIterator implements Iterator {
|
||||
public final class SingletonIterator<T> implements Iterator<T> {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
* <p/>
|
||||
* 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<PrimaryKeyJoinColumnSource> primaryKeyJoinColumnSources = subclassEntitySource.getPrimaryKeyJoinColumnSources();
|
||||
final boolean hasPrimaryKeyJoinColumns = CollectionHelper.isNotEmpty( primaryKeyJoinColumnSources );
|
||||
final List<Column> 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<EntityHierarchy> 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,8 +1638,22 @@ public class Binder {
|
|||
return attributeBinding;
|
||||
}
|
||||
|
||||
private void bindPrimaryTable( final EntityBinding entityBinding, final EntitySource entitySource ) {
|
||||
final TableSpecification table = createTable(
|
||||
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
|
||||
|
@ -1576,8 +1665,10 @@ public class Binder {
|
|||
}
|
||||
}
|
||||
);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -262,7 +262,7 @@ public class EntityClass extends ConfiguredClass {
|
|||
return JandexHelper.getValue( jpaEntityAnnotation, "name", String.class );
|
||||
}
|
||||
|
||||
private List<PrimaryKeyJoinColumnSource> determinPrimaryKeyJoinColumns() {
|
||||
protected List<PrimaryKeyJoinColumnSource> determinPrimaryKeyJoinColumns() {
|
||||
if ( inheritanceType != InheritanceType.JOINED ) {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -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<MappedSuperclass> mappedSuperclasses;
|
||||
|
@ -132,6 +140,14 @@ public class RootEntityClass extends EntityClass {
|
|||
return isDiscriminatorIncludedInSql;
|
||||
}
|
||||
|
||||
protected List<PrimaryKeyJoinColumnSource> determinPrimaryKeyJoinColumns() {
|
||||
List<PrimaryKeyJoinColumnSource> results = super.determinPrimaryKeyJoinColumns();
|
||||
if ( CollectionHelper.isNotEmpty( results ) ) {
|
||||
LOG.invalidPrimaryKeyJoinColumnAnnotation();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<BasicAttribute> getSimpleAttributes() {
|
||||
List<BasicAttribute> attributes = new ArrayList<BasicAttribute>();
|
||||
|
|
|
@ -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() );
|
||||
|
|
|
@ -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<String, AttributeBinding> attributeBindingMap = new HashMap<String, AttributeBinding>();
|
||||
|
||||
private List<JpaCallbackSource> jpaCallbackClasses = new ArrayList<JpaCallbackSource>();
|
||||
|
||||
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<AttributeBinding>( iterables );
|
||||
}
|
||||
|
||||
public Iterator<TableSpecification> getTableClosureIterator() {
|
||||
if ( superEntityBinding == null ) {
|
||||
return new SingletonIterator<TableSpecification>( getPrimaryTable() );
|
||||
}
|
||||
else {
|
||||
return new JoinedIterator<TableSpecification>(
|
||||
superEntityBinding.getTableClosureIterator(),
|
||||
new SingletonIterator<TableSpecification>( getPrimaryTable() )
|
||||
);
|
||||
}
|
||||
}
|
||||
public Iterator getKeyClosureIterator(){
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setJpaCallbackClasses(List<JpaCallbackSource> jpaCallbackClasses) {
|
||||
this.jpaCallbackClasses = jpaCallbackClasses;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -2140,7 +2140,7 @@ public abstract class AbstractCollectionPersister
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize(Serializable key, SessionImplementor session) {
|
||||
try {
|
||||
PreparedStatement st = session.getTransactionCoordinator()
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
@ -211,7 +211,9 @@ public class BasicCollectionPersister extends AbstractCollectionPersister {
|
|||
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 "";
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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<String> tables = new ArrayList<String>();
|
||||
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<TableSpecification> 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 );
|
||||
|
|
|
@ -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<Integer,String> subclassByDiscriminatorValue = new HashMap<Integer,String>();
|
||||
|
||||
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<String> subclassTables = new HashSet<String>();
|
||||
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;
|
||||
|
|
Loading…
Reference in New Issue