HHH-6498 HHH-6337 : Updates to support single-table inheritance using new metamodel
This commit is contained in:
parent
2faeb783a4
commit
dc7feab061
|
@ -83,6 +83,7 @@ import org.hibernate.context.internal.ManagedSessionContext;
|
|||
import org.hibernate.context.internal.ThreadLocalSessionContext;
|
||||
import org.hibernate.context.spi.CurrentSessionContext;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.dialect.function.SQLFunction;
|
||||
import org.hibernate.dialect.function.SQLFunctionRegistry;
|
||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
|
@ -187,8 +188,8 @@ public final class SessionFactoryImpl
|
|||
private final transient Map<String, FetchProfile> fetchProfiles;
|
||||
private final transient Map<String,String> imports;
|
||||
private final transient SessionFactoryServiceRegistry serviceRegistry;
|
||||
private final transient JdbcServices jdbcServices;
|
||||
private final transient Dialect dialect;
|
||||
private final transient JdbcServices jdbcServices;
|
||||
private final transient Dialect dialect;
|
||||
private final transient Settings settings;
|
||||
private final transient Properties properties;
|
||||
private transient SchemaExport schemaExport;
|
||||
|
@ -530,9 +531,6 @@ public final class SessionFactoryImpl
|
|||
SessionFactoryObserver observer) throws HibernateException {
|
||||
LOG.debug( "Building session factory" );
|
||||
|
||||
// TODO: remove initialization of final variables; just setting to null to make compiler happy
|
||||
this.sqlFunctionRegistry = null;
|
||||
|
||||
this.sessionFactoryOptions = sessionFactoryOptions;
|
||||
|
||||
this.properties = createPropertiesFromMap(
|
||||
|
@ -553,6 +551,10 @@ public final class SessionFactoryImpl
|
|||
this.jdbcServices = this.serviceRegistry.getService( JdbcServices.class );
|
||||
this.dialect = this.jdbcServices.getDialect();
|
||||
|
||||
// TODO: get SQL functions from JdbcServices (HHH-6559)
|
||||
//this.sqlFunctionRegistry = new SQLFunctionRegistry( this.jdbcServices.getSqlFunctions() );
|
||||
this.sqlFunctionRegistry = new SQLFunctionRegistry( this.dialect, new HashMap<String, SQLFunction>() );
|
||||
|
||||
// TODO: get SQL functions from a new service
|
||||
// this.sqlFunctionRegistry = new SQLFunctionRegistry( getDialect(), cfg.getSqlFunctions() );
|
||||
|
||||
|
|
|
@ -53,6 +53,9 @@ import org.hibernate.tuple.entity.EntityTuplizer;
|
|||
* @author Gail Badner
|
||||
*/
|
||||
public class EntityBinding implements AttributeBindingContainer {
|
||||
private static final String NULL_DISCRIMINATOR_MATCH_VALUE = "null";
|
||||
private static final String NOT_NULL_DISCRIMINATOR_MATCH_VALUE = "not null";
|
||||
|
||||
private final EntityBinding superEntityBinding;
|
||||
private final List<EntityBinding> subEntityBindings = new ArrayList<EntityBinding>();
|
||||
private final HierarchyDetails hierarchyDetails;
|
||||
|
@ -142,28 +145,70 @@ public class EntityBinding implements AttributeBindingContainer {
|
|||
return subEntityBindings.size() > 0;
|
||||
}
|
||||
|
||||
public int getSubEntityBindingSpan() {
|
||||
public int getSubEntityBindingClosureSpan() {
|
||||
int n = subEntityBindings.size();
|
||||
for ( EntityBinding subEntityBinding : subEntityBindings ) {
|
||||
n += subEntityBinding.getSubEntityBindingSpan();
|
||||
n += subEntityBinding.getSubEntityBindingClosureSpan();
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* used for testing */
|
||||
public Iterable<EntityBinding> getDirectSubEntityBindings() {
|
||||
return subEntityBindings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate over subclasses in a special 'order', most derived subclasses
|
||||
* first.
|
||||
* Returns sub-EntityBinding objects in a special 'order', most derived subclasses
|
||||
* first. Specifically, the sub-entity bindings follow a depth-first,
|
||||
* post-order traversal
|
||||
*
|
||||
* Note that the returned value excludes this entity binding.
|
||||
*
|
||||
* @return sub-entity bindings ordered by those entity bindings that are most derived.
|
||||
*/
|
||||
public Iterable<EntityBinding> getSubEntityBindingClosure() {
|
||||
List<Iterable<EntityBinding>> subclassIterables =
|
||||
new ArrayList<Iterable<EntityBinding>>( subEntityBindings.size() + 1 );
|
||||
public Iterable<EntityBinding> getPostOrderSubEntityBindingClosure() {
|
||||
// TODO: why this order?
|
||||
List<Iterable<EntityBinding>> subclassIterables = new ArrayList<Iterable<EntityBinding>>( subEntityBindings.size() + 1 );
|
||||
for ( EntityBinding subEntityBinding : subEntityBindings ) {
|
||||
subclassIterables.add( subEntityBinding.getSubEntityBindingClosure() );
|
||||
Iterable<EntityBinding> subSubEntityBindings = subEntityBinding.getPostOrderSubEntityBindingClosure();
|
||||
if ( subSubEntityBindings.iterator().hasNext() ) {
|
||||
subclassIterables.add( subSubEntityBindings );
|
||||
}
|
||||
}
|
||||
if ( ! subEntityBindings.isEmpty() ) {
|
||||
subclassIterables.add( subEntityBindings );
|
||||
}
|
||||
subclassIterables.add( subEntityBindings );
|
||||
return new JoinedIterable<EntityBinding>( subclassIterables );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns sub-EntityBinding ordered as a depth-first,
|
||||
* pre-order traversal (a subclass precedes its own subclasses).
|
||||
*
|
||||
* Note that the returned value specifically excludes this entity binding.
|
||||
*
|
||||
* @return sub-entity bindings ordered as a depth-first,
|
||||
* pre-order traversal
|
||||
*/
|
||||
public Iterable<EntityBinding> getPreOrderSubEntityBindingClosure() {
|
||||
return getPreOrderSubEntityBindingClosure( false );
|
||||
}
|
||||
|
||||
private Iterable<EntityBinding> getPreOrderSubEntityBindingClosure(boolean includeThis) {
|
||||
List<Iterable<EntityBinding>> iterables = new ArrayList<Iterable<EntityBinding>>();
|
||||
if ( includeThis ) {
|
||||
iterables.add( java.util.Collections.singletonList( this ) );
|
||||
}
|
||||
for ( EntityBinding subEntityBinding : subEntityBindings ) {
|
||||
Iterable<EntityBinding> subSubEntityBindingClosure = subEntityBinding.getPreOrderSubEntityBindingClosure( true );
|
||||
if ( subSubEntityBindingClosure.iterator().hasNext() ) {
|
||||
iterables.add( subSubEntityBindingClosure );
|
||||
}
|
||||
}
|
||||
return new JoinedIterable<EntityBinding>( iterables );
|
||||
}
|
||||
|
||||
public Entity getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
@ -212,6 +257,14 @@ public class EntityBinding implements AttributeBindingContainer {
|
|||
return getHierarchyDetails().getVersioningAttributeBinding() != null;
|
||||
}
|
||||
|
||||
public boolean isDiscriminatorMatchValueNull() {
|
||||
return NULL_DISCRIMINATOR_MATCH_VALUE.equals( discriminatorMatchValue );
|
||||
}
|
||||
|
||||
public boolean isDiscriminatorMatchValueNotNull() {
|
||||
return NOT_NULL_DISCRIMINATOR_MATCH_VALUE.equals( discriminatorMatchValue );
|
||||
}
|
||||
|
||||
public String getDiscriminatorMatchValue() {
|
||||
return discriminatorMatchValue;
|
||||
}
|
||||
|
@ -521,4 +574,21 @@ public class EntityBinding implements AttributeBindingContainer {
|
|||
}
|
||||
return iterable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the attribute bindings for this EntityBinding and all of its
|
||||
* sub-EntityBinding, starting from the root of the hierarchy; includes
|
||||
* the identifier and attribute bindings defined as part of a join.
|
||||
* @return
|
||||
*/
|
||||
public Iterable<AttributeBinding> getSubEntityAttributeBindingClosure() {
|
||||
List<Iterable<AttributeBinding>> iterables = new ArrayList<Iterable<AttributeBinding>>();
|
||||
iterables.add( getAttributeBindingClosure() );
|
||||
for ( EntityBinding subEntityBinding : getPreOrderSubEntityBindingClosure() ) {
|
||||
// only add attribute bindings declared for the subEntityBinding
|
||||
iterables.add( subEntityBinding.attributeBindings() );
|
||||
// TODO: if EntityBinding.attributeBindings() excludes joined attributes, then they need to be added here
|
||||
}
|
||||
return new JoinedIterable<AttributeBinding>( iterables );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -768,7 +768,6 @@ public abstract class AbstractEntityPersister
|
|||
final EntityBinding entityBinding,
|
||||
final EntityRegionAccessStrategy cacheAccessStrategy,
|
||||
final SessionFactoryImplementor factory) throws HibernateException {
|
||||
// TODO: Implement! Initializing final fields to make compiler happy
|
||||
this.factory = factory;
|
||||
this.cacheAccessStrategy = cacheAccessStrategy;
|
||||
this.isLazyPropertiesCacheable =
|
||||
|
@ -812,8 +811,6 @@ public abstract class AbstractEntityPersister
|
|||
rootTableKeyColumnReaders[i] = col.getReadFragment();
|
||||
rootTableKeyColumnReaderTemplates[i] = getTemplateFromString( col.getReadFragment(), factory );
|
||||
}
|
||||
// TODO: Fix when HHH-6337 is fixed; for now assume entityBinding is the root
|
||||
// identifierAliases[i] = col.getAlias( factory.getDialect(), entityBinding.getRootEntityBinding().getPrimaryTable() );
|
||||
identifierAliases[i] = col.getAlias( factory.getDialect() );
|
||||
i++;
|
||||
}
|
||||
|
@ -915,8 +912,8 @@ public abstract class AbstractEntityPersister
|
|||
propertyColumnWriters[i] = colWriters;
|
||||
propertyColumnAliases[i] = colAliases;
|
||||
|
||||
propertyColumnUpdateable[i] = propertyColumnInsertability;
|
||||
propertyColumnInsertable[i] = propertyColumnUpdatability;
|
||||
propertyColumnUpdateable[i] = propertyColumnUpdatability;
|
||||
propertyColumnInsertable[i] = propertyColumnInsertability;
|
||||
|
||||
if ( lazyAvailable && singularAttributeBinding.isLazy() ) {
|
||||
lazyProperties.add( singularAttributeBinding.getAttribute().getName() );
|
||||
|
@ -967,9 +964,7 @@ public abstract class AbstractEntityPersister
|
|||
List<Boolean> columnSelectables = new ArrayList<Boolean>();
|
||||
List<Boolean> propNullables = new ArrayList<Boolean>();
|
||||
|
||||
// TODO: fix this when EntityBinding.getSubclassAttributeBindingClosure() is working
|
||||
// for ( AttributeBinding prop : entityBinding.getSubclassAttributeBindingClosure() ) {
|
||||
for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) {
|
||||
for ( AttributeBinding attributeBinding : entityBinding.getSubEntityAttributeBindingClosure() ) {
|
||||
if ( attributeBinding == entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ) {
|
||||
// entity identifier is not considered a "normal" property
|
||||
continue;
|
||||
|
|
|
@ -466,8 +466,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
isNullableTable = new boolean[joinSpan];
|
||||
keyColumnNames = new String[joinSpan][];
|
||||
|
||||
// TODO: fix when EntityBinhding.getRootEntityBinding() exists (HHH-6337)
|
||||
//final Table table = entityBinding.getRootEntityBinding().getPrimaryTable();
|
||||
final TableSpecification table = entityBinding.getPrimaryTable();
|
||||
qualifiedTableNames[0] = table.getQualifiedName( factory.getDialect() );
|
||||
isInverseTable[0] = false;
|
||||
|
@ -538,15 +536,8 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
|
||||
// DISCRIMINATOR
|
||||
|
||||
// TODO: fix this when can get subclass info from EntityBinding (HHH-6337)
|
||||
// for now set hasSubclasses to false
|
||||
//hasSubclasses = entityBinding.hasSubclasses();
|
||||
boolean hasSubclasses = false;
|
||||
|
||||
//polymorphic = ! entityBinding.isRoot() || entityBinding.hasSubclasses();
|
||||
boolean isPolymorphic = ! entityBinding.isRoot() || hasSubclasses;
|
||||
final Object discriminatorValue;
|
||||
if ( isPolymorphic ) {
|
||||
if ( entityBinding.isPolymorphic() ) {
|
||||
SimpleValue discriminatorRelationalValue = entityBinding.getHierarchyDetails().getEntityDiscriminator().getBoundValue();
|
||||
if ( discriminatorRelationalValue == null ) {
|
||||
throw new MappingException("discriminator mapping required for single table polymorphic persistence");
|
||||
|
@ -569,9 +560,6 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
column.getColumnName().encloseInQuotesIfQuoted( factory.getDialect() ) :
|
||||
column.getReadFragment();
|
||||
discriminatorColumnReaderTemplate = getTemplateFromColumn( column, factory );
|
||||
// TODO: fix this when EntityBinding.getRootEntityBinding() is implemented;
|
||||
// for now, assume entityBinding is the root
|
||||
//discriminatorAlias = column.getAlias( factory.getDialect(), entityBinding.getRootEntityBinding().getPrimaryTable );
|
||||
discriminatorAlias = column.getAlias( factory.getDialect() );
|
||||
discriminatorFormula = null;
|
||||
discriminatorFormulaTemplate = null;
|
||||
|
@ -648,9 +636,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
ArrayList formulaJoinedNumbers = new ArrayList();
|
||||
ArrayList propertyJoinNumbers = new ArrayList();
|
||||
|
||||
// TODO: fix when subclasses are working (HHH-6337)
|
||||
//for ( AttributeBinding prop : entityBinding.getSubclassAttributeBindingClosure() ) {
|
||||
for ( AttributeBinding attributeBinding : entityBinding.getAttributeBindingClosure() ) {
|
||||
for ( AttributeBinding attributeBinding : entityBinding.getSubEntityAttributeBindingClosure() ) {
|
||||
if ( ! attributeBinding.getAttribute().isSingular() ) {
|
||||
continue;
|
||||
}
|
||||
|
@ -680,18 +666,41 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
subclassFormulaTableNumberClosure = ArrayHelper.toIntArray(formulaJoinedNumbers);
|
||||
subclassPropertyTableNumberClosure = ArrayHelper.toIntArray(propertyJoinNumbers);
|
||||
|
||||
// TODO; fix when subclasses are working (HHH-6337)
|
||||
//int subclassSpan = entityBinding.getSubclassSpan() + 1;
|
||||
int subclassSpan = 1;
|
||||
int subclassSpan = entityBinding.getSubEntityBindingClosureSpan() + 1;
|
||||
subclassClosure = new String[subclassSpan];
|
||||
subclassClosure[0] = getEntityName();
|
||||
if ( isPolymorphic ) {
|
||||
if ( entityBinding.isPolymorphic() ) {
|
||||
subclassesByDiscriminatorValue.put( discriminatorValue, getEntityName() );
|
||||
}
|
||||
|
||||
// SUBCLASSES
|
||||
|
||||
// TODO; fix when subclasses are working (HHH-6337)
|
||||
if ( entityBinding.isPolymorphic() ) {
|
||||
int k=1;
|
||||
for ( EntityBinding subEntityBinding : entityBinding.getPostOrderSubEntityBindingClosure() ) {
|
||||
subclassClosure[k++] = subEntityBinding.getEntity().getName();
|
||||
if ( subEntityBinding.isDiscriminatorMatchValueNull() ) {
|
||||
subclassesByDiscriminatorValue.put( NULL_DISCRIMINATOR, subEntityBinding.getEntity().getName() );
|
||||
}
|
||||
else if ( subEntityBinding.isDiscriminatorMatchValueNotNull() ) {
|
||||
subclassesByDiscriminatorValue.put( NOT_NULL_DISCRIMINATOR, subEntityBinding.getEntity().getName() );
|
||||
}
|
||||
else {
|
||||
try {
|
||||
DiscriminatorType dtype = (DiscriminatorType) discriminatorType;
|
||||
subclassesByDiscriminatorValue.put(
|
||||
dtype.stringToObject( subEntityBinding.getDiscriminatorMatchValue() ),
|
||||
subEntityBinding.getEntity().getName()
|
||||
);
|
||||
}
|
||||
catch (ClassCastException cce) {
|
||||
throw new MappingException("Illegal discriminator type: " + discriminatorType.getName() );
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new MappingException("Error parsing discriminator value", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
initLockers();
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.HashSet;
|
|||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.metamodel.binding.EntityBinding;
|
||||
|
||||
|
@ -58,14 +59,9 @@ public class DynamicMapInstantiator implements Instantiator {
|
|||
public DynamicMapInstantiator(EntityBinding mappingInfo) {
|
||||
this.entityName = mappingInfo.getEntity().getName();
|
||||
isInstanceEntityNames.add( entityName );
|
||||
// TODO: fix this when can get subclass info from EntityBinding (HHH-6337)
|
||||
//if ( mappingInfo.hasSubclasses() ) {
|
||||
// Iterator itr = mappingInfo.getSubclassClosureIterator();
|
||||
// while ( itr.hasNext() ) {
|
||||
// final PersistentClass subclassInfo = ( PersistentClass ) itr.next();
|
||||
// isInstanceEntityNames.add( subclassInfo.getEntityName() );
|
||||
// }
|
||||
//}
|
||||
for ( EntityBinding subEntityBinding : mappingInfo.getPostOrderSubEntityBindingClosure() ) {
|
||||
isInstanceEntityNames.add( subEntityBinding.getEntity().getName() );
|
||||
}
|
||||
}
|
||||
|
||||
public final Object instantiate(Serializable id) {
|
||||
|
|
|
@ -360,9 +360,7 @@ public class EntityMetamodel implements Serializable {
|
|||
|
||||
name = entityBinding.getEntity().getName();
|
||||
|
||||
// TODO: Fix after HHH-6337 is fixed; for now assume entityBinding is the root binding
|
||||
//rootName = entityBinding.getRootEntityBinding().getName();
|
||||
rootName = name;
|
||||
rootName = entityBinding.getHierarchyDetails().getRootEntityBinding().getEntity().getName();
|
||||
entityType = sessionFactory.getTypeResolver().getTypeFactory().manyToOne( name );
|
||||
|
||||
identifierProperty = PropertyFactory.buildIdentifierProperty(
|
||||
|
@ -386,7 +384,6 @@ public class EntityMetamodel implements Serializable {
|
|||
boolean hasLazy = false;
|
||||
|
||||
// TODO: Fix after HHH-6337 is fixed; for now assume entityBinding is the root binding
|
||||
//BasicAttributeBinding rootEntityIdentifier = entityBinding.getRootEntityBinding().getEntityIdentifier().getValueBinding();
|
||||
BasicAttributeBinding rootEntityIdentifier = entityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding();
|
||||
// entityBinding.getAttributeClosureSpan() includes the identifier binding;
|
||||
// "properties" here excludes the ID, so subtract 1 if the identifier binding is non-null
|
||||
|
@ -540,13 +537,8 @@ public class EntityMetamodel implements Serializable {
|
|||
dynamicUpdate = entityBinding.isDynamicUpdate();
|
||||
dynamicInsert = entityBinding.isDynamicInsert();
|
||||
|
||||
// TODO: fix this when can get subclass info from EntityBinding (HHH-6337)
|
||||
// for now set hasSubclasses to false
|
||||
//hasSubclasses = entityBinding.hasSubclasses();
|
||||
hasSubclasses = false;
|
||||
|
||||
//polymorphic = ! entityBinding.isRoot() || entityBinding.hasSubclasses();
|
||||
polymorphic = ! entityBinding.isRoot() || hasSubclasses;
|
||||
hasSubclasses = entityBinding.hasSubEntityBindings();
|
||||
polymorphic = entityBinding.isPolymorphic();
|
||||
|
||||
explicitPolymorphism = entityBinding.getHierarchyDetails().isExplicitPolymorphism();
|
||||
inherited = ! entityBinding.isRoot();
|
||||
|
@ -568,24 +560,17 @@ public class EntityMetamodel implements Serializable {
|
|||
hasCollections = foundCollection;
|
||||
hasMutableProperties = foundMutable;
|
||||
|
||||
// TODO: fix this when can get subclass info from EntityBinding (HHH-6337)
|
||||
// TODO: uncomment when it's possible to get subclasses from an EntityBinding
|
||||
//iter = entityBinding.getSubclassIterator();
|
||||
//while ( iter.hasNext() ) {
|
||||
// subclassEntityNames.add( ( (PersistentClass) iter.next() ).getEntityName() );
|
||||
//}
|
||||
for ( EntityBinding subEntityBinding : entityBinding.getPostOrderSubEntityBindingClosure() ) {
|
||||
subclassEntityNames.add( subEntityBinding.getEntity().getName() );
|
||||
if ( subEntityBinding.getEntity().getClassReference() != null ) {
|
||||
entityNameByInheritenceClassMap.put(
|
||||
subEntityBinding.getEntity().getClassReference(),
|
||||
subEntityBinding.getEntity().getName() );
|
||||
}
|
||||
}
|
||||
subclassEntityNames.add( name );
|
||||
|
||||
if ( mappedClass != null ) {
|
||||
entityNameByInheritenceClassMap.put( mappedClass, name );
|
||||
// TODO: uncomment when it's possible to get subclasses from an EntityBinding
|
||||
// iter = entityBinding.getSubclassIterator();
|
||||
// while ( iter.hasNext() ) {
|
||||
// final EntityBinding subclassEntityBinding = ( EntityBinding ) iter.next();
|
||||
// entityNameByInheritenceClassMap.put(
|
||||
// subclassEntityBinding.getEntity().getPojoEntitySpecifics().getEntityClass(),
|
||||
// subclassEntityBinding.getEntity().getName() );
|
||||
// }
|
||||
}
|
||||
|
||||
entityMode = hasPojoRepresentation ? EntityMode.POJO : EntityMode.MAP;
|
||||
|
|
|
@ -278,21 +278,18 @@ public class PojoEntityTuplizer extends AbstractEntityTuplizer {
|
|||
proxyInterfaces.add( mappedClass );
|
||||
}
|
||||
|
||||
// TODO: fix when it's possible to get subclasses from an EntityBinding
|
||||
//Iterator subclasses = entityBinding.getSubclassIterator();
|
||||
//while ( subclasses.hasNext() ) {
|
||||
// final Subclass subclass = ( Subclass ) subclasses.next();
|
||||
// final Class subclassProxy = subclass.getProxyInterface();
|
||||
// final Class subclassClass = subclass.getMappedClass();
|
||||
// if ( subclassProxy!=null && !subclassClass.equals( subclassProxy ) ) {
|
||||
// if ( !subclassProxy.isInterface() ) {
|
||||
// throw new MappingException(
|
||||
// "proxy must be either an interface, or the class itself: " + subclass.getEntityName()
|
||||
// );
|
||||
// }
|
||||
// proxyInterfaces.add( subclassProxy );
|
||||
// }
|
||||
//}
|
||||
for ( EntityBinding subEntityBinding : entityBinding.getPostOrderSubEntityBindingClosure() ) {
|
||||
final Class subclassProxy = subEntityBinding.getProxyInterfaceType().getValue();
|
||||
final Class subclassClass = subEntityBinding.getClassReference();
|
||||
if ( subclassProxy!=null && !subclassClass.equals( subclassProxy ) ) {
|
||||
if ( ! subclassProxy.isInterface() ) {
|
||||
throw new MappingException(
|
||||
"proxy must be either an interface, or the class itself: " + subEntityBinding.getEntity().getName()
|
||||
);
|
||||
}
|
||||
proxyInterfaces.add( subclassProxy );
|
||||
}
|
||||
}
|
||||
|
||||
for ( AttributeBinding property : entityBinding.attributeBindings() ) {
|
||||
Method method = getGetter( property ).getMethod();
|
||||
|
|
|
@ -23,8 +23,10 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.source.annotations.entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.DiscriminatorType;
|
||||
|
@ -121,14 +123,31 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
assertSame( noInheritanceEntityBinding, getRootEntityBinding( SingleEntity.class ) );
|
||||
assertFalse( noInheritanceEntityBinding.isPolymorphic() );
|
||||
assertFalse( noInheritanceEntityBinding.hasSubEntityBindings() );
|
||||
assertEquals( 0, noInheritanceEntityBinding.getSubEntityBindingSpan() );
|
||||
assertFalse( noInheritanceEntityBinding.getSubEntityBindingClosure().iterator().hasNext() );
|
||||
assertEquals( 1, noInheritanceEntityBinding.getAttributeBindingClosureSpan() );
|
||||
for ( AttributeBinding attributeBinding : noInheritanceEntityBinding.getAttributeBindingClosure() ) {
|
||||
if ( attributeBinding == noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ) {
|
||||
continue;
|
||||
}
|
||||
assertEquals( 0, noInheritanceEntityBinding.getSubEntityBindingClosureSpan() );
|
||||
assertFalse( noInheritanceEntityBinding.getPostOrderSubEntityBindingClosure().iterator().hasNext() );
|
||||
assertFalse( noInheritanceEntityBinding.getPreOrderSubEntityBindingClosure().iterator().hasNext() );
|
||||
Set<AttributeBinding> directAttributeBindings = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding attributeBinding : noInheritanceEntityBinding.attributeBindings() ) {
|
||||
assertTrue( directAttributeBindings.add( attributeBinding ) );
|
||||
}
|
||||
assertEquals( 1, directAttributeBindings.size() );
|
||||
assertSame(
|
||||
noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(),
|
||||
directAttributeBindings.iterator().next()
|
||||
);
|
||||
assertEquals( 1, noInheritanceEntityBinding.getAttributeBindingClosureSpan() );
|
||||
Iterator<AttributeBinding> iterator = noInheritanceEntityBinding.attributeBindings().iterator();
|
||||
assertTrue( iterator.hasNext() );
|
||||
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), iterator.next() );
|
||||
assertFalse( iterator.hasNext() );
|
||||
iterator = noInheritanceEntityBinding.getAttributeBindingClosure().iterator();
|
||||
assertTrue( iterator.hasNext() );
|
||||
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), iterator.next() );
|
||||
assertFalse( iterator.hasNext() );
|
||||
iterator = noInheritanceEntityBinding.getSubEntityAttributeBindingClosure().iterator();
|
||||
assertTrue( iterator.hasNext() );
|
||||
assertSame( noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding(), iterator.next() );
|
||||
assertFalse( iterator.hasNext() );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -151,22 +170,110 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
assertSame( rootEntityBinding, getRootEntityBinding( RootOfSingleTableInheritance.class ) );
|
||||
assertTrue( rootEntityBinding.isPolymorphic() );
|
||||
assertTrue( rootEntityBinding.hasSubEntityBindings() );
|
||||
assertEquals( 3, rootEntityBinding.getSubEntityBindingSpan() );
|
||||
Set<EntityBinding> subEntityBindings = new HashSet<EntityBinding>( );
|
||||
for ( EntityBinding subEntityBinding : rootEntityBinding.getSubEntityBindingClosure() ) {
|
||||
subEntityBindings.add( subEntityBinding );
|
||||
Iterator<EntityBinding> directEntityBindingIterator = rootEntityBinding.getDirectSubEntityBindings().iterator();
|
||||
assertTrue( directEntityBindingIterator.hasNext() );
|
||||
EntityBinding directSubEntityBinding1 = directEntityBindingIterator.next();
|
||||
assertTrue( directEntityBindingIterator.hasNext() );
|
||||
EntityBinding directSubEntityBinding2 = directEntityBindingIterator.next();
|
||||
assertFalse( directEntityBindingIterator.hasNext() );
|
||||
boolean isSubclassEntityBindingFirst = directSubEntityBinding1 == subclassEntityBinding;
|
||||
if ( isSubclassEntityBindingFirst ) {
|
||||
assertSame( otherSubclassEntityBinding, directSubEntityBinding2 );
|
||||
}
|
||||
assertEquals( 3, subEntityBindings.size() );
|
||||
assertTrue( subEntityBindings.contains( subclassEntityBinding ) );
|
||||
assertTrue( subEntityBindings.contains( otherSubclassEntityBinding ) );
|
||||
assertTrue( subEntityBindings.contains( subclassOfSubclassEntityBinding ) );
|
||||
else {
|
||||
assertSame( otherSubclassEntityBinding, directSubEntityBinding1 );
|
||||
assertSame( subclassEntityBinding, directSubEntityBinding2 );
|
||||
}
|
||||
Set<AttributeBinding> directAttributeBindings = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding attributeBinding : rootEntityBinding.attributeBindings() ) {
|
||||
assertTrue( directAttributeBindings.add( attributeBinding ) );
|
||||
}
|
||||
assertEquals( 1, directAttributeBindings.size() );
|
||||
assertTrue( directAttributeBindings.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
||||
assertEquals( 1, rootEntityBinding.getAttributeBindingClosureSpan() );
|
||||
Set<String> attributeNames = new HashSet<String>();
|
||||
Set<AttributeBinding> attributeBindingClosure = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding attributeBinding : rootEntityBinding.getAttributeBindingClosure() ) {
|
||||
attributeNames.add( attributeBinding.getAttribute().getName() );
|
||||
assertTrue( attributeBindingClosure.add( attributeBinding ) );
|
||||
}
|
||||
assertEquals( 1, attributeNames.size() );
|
||||
assertTrue( attributeNames.contains( "id" ) );
|
||||
assertEquals( 1, attributeBindingClosure.size() );
|
||||
assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
||||
Set<AttributeBinding> subAttributeBindings = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding subAttributeBinding : rootEntityBinding.getSubEntityAttributeBindingClosure() ) {
|
||||
assertTrue( subAttributeBindings.add( subAttributeBinding ) );
|
||||
}
|
||||
assertEquals( 4, subAttributeBindings.size() );
|
||||
assertTrue( subAttributeBindings.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
||||
assertTrue( subAttributeBindings.contains( subclassEntityBinding.locateAttributeBinding( "name" ) ) );
|
||||
assertTrue( subAttributeBindings.contains( subclassOfSubclassEntityBinding.locateAttributeBinding( "otherOtherName" ) ) );
|
||||
assertTrue( subAttributeBindings.contains( otherSubclassEntityBinding.locateAttributeBinding( "otherName" ) ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
@Resources(annotatedClasses = {
|
||||
SubclassOfSingleTableInheritance.class,
|
||||
SingleEntity.class,
|
||||
RootOfSingleTableInheritance.class,
|
||||
OtherSubclassOfSingleTableInheritance.class,
|
||||
SubclassOfSubclassOfSingleTableInheritance.class
|
||||
})
|
||||
public void testPreOrderRootSubEntityClosure() {
|
||||
EntityBinding rootEntityBinding = getEntityBinding( RootOfSingleTableInheritance.class );
|
||||
EntityBinding subclassEntityBinding = getEntityBinding( SubclassOfSingleTableInheritance.class );
|
||||
EntityBinding otherSubclassEntityBinding = getEntityBinding( OtherSubclassOfSingleTableInheritance.class );
|
||||
EntityBinding subclassOfSubclassEntityBinding = getEntityBinding( SubclassOfSubclassOfSingleTableInheritance.class );
|
||||
// need to figure out the order of direct subclasses, since it's indeterminate
|
||||
Iterator<EntityBinding> directEntityBindingIterator = rootEntityBinding.getDirectSubEntityBindings().iterator();
|
||||
boolean isSubclassEntityBindingFirst = subclassEntityBinding == directEntityBindingIterator.next();
|
||||
assertEquals( 3, rootEntityBinding.getSubEntityBindingClosureSpan() );
|
||||
Iterator<EntityBinding> subEntityBindingIterator = rootEntityBinding.getPreOrderSubEntityBindingClosure().iterator();
|
||||
assertTrue( subEntityBindingIterator.hasNext() );
|
||||
if ( isSubclassEntityBindingFirst ) {
|
||||
assertSame( subclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertTrue( subEntityBindingIterator.hasNext() );
|
||||
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertTrue( subEntityBindingIterator.hasNext() );
|
||||
assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() );
|
||||
}
|
||||
else {
|
||||
assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertTrue( subEntityBindingIterator.hasNext() );
|
||||
assertSame( subclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertTrue( subEntityBindingIterator.hasNext() );
|
||||
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() );
|
||||
}
|
||||
assertFalse( subEntityBindingIterator.hasNext() );
|
||||
}
|
||||
|
||||
@Test
|
||||
@Resources(annotatedClasses = {
|
||||
SubclassOfSingleTableInheritance.class,
|
||||
SingleEntity.class,
|
||||
RootOfSingleTableInheritance.class,
|
||||
OtherSubclassOfSingleTableInheritance.class,
|
||||
SubclassOfSubclassOfSingleTableInheritance.class
|
||||
})
|
||||
public void testPostOrderRootSubEntityClosure() {
|
||||
EntityBinding rootEntityBinding = getEntityBinding( RootOfSingleTableInheritance.class );
|
||||
EntityBinding subclassEntityBinding = getEntityBinding( SubclassOfSingleTableInheritance.class );
|
||||
EntityBinding otherSubclassEntityBinding = getEntityBinding( OtherSubclassOfSingleTableInheritance.class );
|
||||
EntityBinding subclassOfSubclassEntityBinding = getEntityBinding( SubclassOfSubclassOfSingleTableInheritance.class );
|
||||
// need to figure out the order of direct subclasses, since it's indeterminate
|
||||
Iterator<EntityBinding> directEntityBindingIterator = rootEntityBinding.getDirectSubEntityBindings().iterator();
|
||||
boolean isSubclassEntityBindingFirst = subclassEntityBinding == directEntityBindingIterator.next();
|
||||
assertEquals( 3, rootEntityBinding.getSubEntityBindingClosureSpan() );
|
||||
Iterator<EntityBinding> subEntityBindingIterator = rootEntityBinding.getPostOrderSubEntityBindingClosure().iterator();
|
||||
assertTrue( subEntityBindingIterator.hasNext() );
|
||||
if ( isSubclassEntityBindingFirst ) {
|
||||
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertSame( subclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() );
|
||||
}
|
||||
else {
|
||||
assertSame( subclassOfSubclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertSame( otherSubclassEntityBinding, subEntityBindingIterator.next() );
|
||||
assertSame( subclassEntityBinding, subEntityBindingIterator.next() );
|
||||
}
|
||||
assertFalse( subEntityBindingIterator.hasNext() );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -189,16 +296,30 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
assertSame( rootEntityBinding, getRootEntityBinding( OtherSubclassOfSingleTableInheritance.class) );
|
||||
assertTrue( otherSubclassEntityBinding.isPolymorphic() );
|
||||
assertFalse( otherSubclassEntityBinding.hasSubEntityBindings() );
|
||||
assertEquals( 0, otherSubclassEntityBinding.getSubEntityBindingSpan() );
|
||||
assertFalse( otherSubclassEntityBinding.getSubEntityBindingClosure().iterator().hasNext() );
|
||||
assertEquals( 2, otherSubclassEntityBinding.getAttributeBindingClosureSpan() );
|
||||
Set<String> attributeNames = new HashSet<String>();
|
||||
for ( AttributeBinding attributeBinding : otherSubclassEntityBinding.getAttributeBindingClosure() ) {
|
||||
attributeNames.add( attributeBinding.getAttribute().getName() );
|
||||
assertEquals( 0, otherSubclassEntityBinding.getSubEntityBindingClosureSpan() );
|
||||
assertFalse( otherSubclassEntityBinding.getPostOrderSubEntityBindingClosure().iterator().hasNext() );
|
||||
assertFalse( otherSubclassEntityBinding.getPreOrderSubEntityBindingClosure().iterator().hasNext() );
|
||||
Set<AttributeBinding> directAttributeBindings = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding attributeBinding : otherSubclassEntityBinding.attributeBindings() ) {
|
||||
assertTrue( directAttributeBindings.add( attributeBinding ) );
|
||||
}
|
||||
assertEquals( 2, attributeNames.size() );
|
||||
assertTrue( attributeNames.contains( "id" ) );
|
||||
assertTrue( attributeNames.contains( "otherName" ) );
|
||||
assertEquals( 1, directAttributeBindings.size() );
|
||||
assertTrue( directAttributeBindings.contains( otherSubclassEntityBinding.locateAttributeBinding( "otherName" ) ) );
|
||||
assertEquals( 2, otherSubclassEntityBinding.getAttributeBindingClosureSpan() );
|
||||
Set<AttributeBinding> attributeBindingClosure = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding attributeBinding : otherSubclassEntityBinding.getAttributeBindingClosure() ) {
|
||||
assertTrue( attributeBindingClosure.add( attributeBinding ) );
|
||||
}
|
||||
assertEquals(2, attributeBindingClosure.size() );
|
||||
assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
||||
assertTrue( attributeBindingClosure.contains( otherSubclassEntityBinding.locateAttributeBinding( "otherName" ) ) );
|
||||
Set<AttributeBinding> subAttributeBindings = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding subAttributeBinding : otherSubclassEntityBinding.getSubEntityAttributeBindingClosure() ) {
|
||||
assertTrue( subAttributeBindings.add( subAttributeBinding ) );
|
||||
}
|
||||
assertEquals( 2, subAttributeBindings.size() );
|
||||
assertTrue( subAttributeBindings.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
||||
assertTrue( subAttributeBindings.contains( otherSubclassEntityBinding.locateAttributeBinding( "otherName" ) ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -221,19 +342,37 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
assertSame( rootEntityBinding, getRootEntityBinding( SubclassOfSingleTableInheritance.class ) );
|
||||
assertTrue( subclassEntityBinding.isPolymorphic() );
|
||||
assertTrue( subclassEntityBinding.hasSubEntityBindings() );
|
||||
assertEquals( 1, subclassEntityBinding.getSubEntityBindingSpan() );
|
||||
Iterator<EntityBinding> itSubEntityBindings = subclassEntityBinding.getSubEntityBindingClosure().iterator();
|
||||
assertEquals( 1, subclassEntityBinding.getSubEntityBindingClosureSpan() );
|
||||
Iterator<EntityBinding> itSubEntityBindings = subclassEntityBinding.getPostOrderSubEntityBindingClosure().iterator();
|
||||
assertTrue( itSubEntityBindings.hasNext() );
|
||||
assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings.next() );
|
||||
assertFalse( itSubEntityBindings.hasNext() );
|
||||
assertEquals( 2, subclassEntityBinding.getAttributeBindingClosureSpan() );
|
||||
Set<String> attributeNames = new HashSet<String>();
|
||||
for ( AttributeBinding attributeBinding : subclassEntityBinding.getAttributeBindingClosure() ) {
|
||||
attributeNames.add( attributeBinding.getAttribute().getName() );
|
||||
itSubEntityBindings = subclassEntityBinding.getPreOrderSubEntityBindingClosure().iterator();
|
||||
assertTrue( itSubEntityBindings.hasNext() );
|
||||
assertSame( subclassOfSubclassEntityBinding, itSubEntityBindings.next() );
|
||||
assertFalse( itSubEntityBindings.hasNext() );
|
||||
Set<AttributeBinding> directAttributeBindings = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding attributeBinding : subclassEntityBinding.attributeBindings() ) {
|
||||
assertTrue( directAttributeBindings.add( attributeBinding ) );
|
||||
}
|
||||
assertEquals( 2, attributeNames.size() );
|
||||
assertTrue( attributeNames.contains( "id" ) );
|
||||
assertTrue( attributeNames.contains( "name" ) );
|
||||
assertEquals( 1, directAttributeBindings.size() );
|
||||
assertTrue( directAttributeBindings.contains( subclassEntityBinding.locateAttributeBinding( "name" ) ) );
|
||||
assertEquals( 2, subclassEntityBinding.getAttributeBindingClosureSpan() );
|
||||
Set<AttributeBinding> attributeBindingClosure = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding attributeBinding : subclassEntityBinding.getAttributeBindingClosure() ) {
|
||||
assertTrue( attributeBindingClosure.add( attributeBinding ) );
|
||||
}
|
||||
assertEquals( 2, attributeBindingClosure.size() );
|
||||
assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
||||
assertTrue( attributeBindingClosure.contains( subclassEntityBinding.locateAttributeBinding( "name" ) ) );
|
||||
Set<AttributeBinding> subAttributeBindings = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding subAttributeBinding : subclassEntityBinding.getSubEntityAttributeBindingClosure() ) {
|
||||
assertTrue( subAttributeBindings.add( subAttributeBinding ) );
|
||||
}
|
||||
assertEquals( 3, subAttributeBindings.size() );
|
||||
assertTrue( subAttributeBindings.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
||||
assertTrue( subAttributeBindings.contains( subclassEntityBinding.locateAttributeBinding( "name" ) ) );
|
||||
assertTrue( subAttributeBindings.contains( subclassOfSubclassEntityBinding.locateAttributeBinding( "otherOtherName" ) ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -256,17 +395,32 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
assertSame( rootEntityBinding, getRootEntityBinding( SubclassOfSubclassOfSingleTableInheritance.class ) );
|
||||
assertTrue( subclassOfSubclassEntityBinding.isPolymorphic() );
|
||||
assertFalse( subclassOfSubclassEntityBinding.hasSubEntityBindings() );
|
||||
assertEquals( 0, subclassOfSubclassEntityBinding.getSubEntityBindingSpan() );
|
||||
assertFalse( subclassOfSubclassEntityBinding.getSubEntityBindingClosure().iterator().hasNext() );
|
||||
assertEquals( 3, subclassOfSubclassEntityBinding.getAttributeBindingClosureSpan() );
|
||||
Set<String> attributeNames = new HashSet<String>();
|
||||
for ( AttributeBinding attributeBinding : subclassOfSubclassEntityBinding.getAttributeBindingClosure() ) {
|
||||
attributeNames.add( attributeBinding.getAttribute().getName() );
|
||||
assertEquals( 0, subclassOfSubclassEntityBinding.getSubEntityBindingClosureSpan() );
|
||||
assertFalse( subclassOfSubclassEntityBinding.getPostOrderSubEntityBindingClosure().iterator().hasNext() );
|
||||
assertFalse( subclassOfSubclassEntityBinding.getPreOrderSubEntityBindingClosure().iterator().hasNext() );
|
||||
Set<AttributeBinding> directAttributeBindings = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding attributeBinding : subclassOfSubclassEntityBinding.attributeBindings() ) {
|
||||
assertTrue( directAttributeBindings.add( attributeBinding ) );
|
||||
}
|
||||
assertEquals( 3, attributeNames.size() );
|
||||
assertTrue( attributeNames.contains( "id" ) );
|
||||
assertTrue( attributeNames.contains( "name" ) );
|
||||
assertTrue( attributeNames.contains( "otherOtherName" ) );
|
||||
assertEquals( 1, directAttributeBindings.size() );
|
||||
assertTrue( directAttributeBindings.contains( subclassOfSubclassEntityBinding.locateAttributeBinding( "otherOtherName" ) ) );
|
||||
assertEquals( 3, subclassOfSubclassEntityBinding.getAttributeBindingClosureSpan() );
|
||||
Set<AttributeBinding> attributeBindingClosure = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding attributeBinding : subclassOfSubclassEntityBinding.getAttributeBindingClosure() ) {
|
||||
assertTrue( attributeBindingClosure.add( attributeBinding ) );
|
||||
}
|
||||
assertEquals( 3, attributeBindingClosure.size() );
|
||||
assertTrue( attributeBindingClosure.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
||||
assertTrue( attributeBindingClosure.contains( subclassEntityBinding.locateAttributeBinding( "name" ) ) );
|
||||
assertTrue( attributeBindingClosure.contains( subclassOfSubclassEntityBinding.locateAttributeBinding( "otherOtherName" ) ) );
|
||||
Set<AttributeBinding> subAttributeBindings = new HashSet<AttributeBinding>();
|
||||
for ( AttributeBinding subAttributeBinding : subclassOfSubclassEntityBinding.getSubEntityAttributeBindingClosure() ) {
|
||||
assertTrue( subAttributeBindings.add( subAttributeBinding ) );
|
||||
}
|
||||
assertEquals( 3, subAttributeBindings.size() );
|
||||
assertTrue( subAttributeBindings.contains( rootEntityBinding.locateAttributeBinding( "id" ) ) );
|
||||
assertTrue( subAttributeBindings.contains( subclassEntityBinding.locateAttributeBinding( "name" ) ) );
|
||||
assertTrue( subAttributeBindings.contains( subclassOfSubclassEntityBinding.locateAttributeBinding( "otherOtherName" ) ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
//$Id: Employee.java 4373 2004-08-18 09:18:34Z oneovthafew $
|
||||
package org.hibernate.test.discriminator;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* @author Gail Badner
|
||||
*/
|
||||
public class PartTimeEmployee extends Employee {
|
||||
private String title;
|
||||
private BigDecimal salary;
|
||||
private Employee manager;
|
||||
private int percent;
|
||||
|
||||
public int getPercent() {
|
||||
return percent;
|
||||
}
|
||||
|
||||
public void setPercent(int percent) {
|
||||
this.percent = percent;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
<?xml version="1.0"?>
|
||||
<hibernate-mapping package="org.hibernate.test.discriminator" default-access="field"
|
||||
xmlns="http://www.hibernate.org/xsd/hibernate-mapping"
|
||||
xsi:schemaLocation="http://www.hibernate.org/xsd/hibernate-mapping hibernate-mapping-4.0.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
|
||||
<!--
|
||||
<!DOCTYPE hibernate-mapping PUBLIC
|
||||
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
|
||||
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
|
||||
<hibernate-mapping
|
||||
package="org.hibernate.test.discriminator"
|
||||
default-access="field">
|
||||
-->
|
||||
<!--
|
||||
|
||||
This mapping demonstrates a simple table-per-hierarchy mapping strategy;
|
||||
each subclass has simple properties
|
||||
|
||||
-->
|
||||
|
||||
<class name="Person"
|
||||
discriminator-value="P">
|
||||
|
||||
<id name="id"
|
||||
column="person_id"
|
||||
unsaved-value="0">
|
||||
<generator class="assigned"/>
|
||||
</id>
|
||||
|
||||
<discriminator column="TYPE" type="character"/>
|
||||
|
||||
<property name="name"
|
||||
not-null="true"
|
||||
length="80"/>
|
||||
|
||||
<property name="sex"
|
||||
not-null="true"
|
||||
update="false"/>
|
||||
|
||||
<subclass name="Employee"
|
||||
discriminator-value="E">
|
||||
<property name="title" length="20"/>
|
||||
<property name="salary" />
|
||||
<!-- commented out until HHH-6551 is fixed
|
||||
<subclass name="PartTimeEmployee" discriminator-value="M">
|
||||
<property name="percent"/>
|
||||
</subclass>
|
||||
-->
|
||||
</subclass>
|
||||
|
||||
<subclass name="Customer"
|
||||
discriminator-value="C">
|
||||
<property name="comments"/>
|
||||
</subclass>
|
||||
|
||||
</class>
|
||||
|
||||
|
||||
</hibernate-mapping>
|
|
@ -0,0 +1,271 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2006-2011, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.test.discriminator;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.Transaction;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.criterion.Property;
|
||||
import org.hibernate.criterion.Restrictions;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class SimpleInheritanceTest extends BaseCoreFunctionalTestCase {
|
||||
public void configure(Configuration cfg) {
|
||||
super.configure( cfg );
|
||||
cfg.setProperty( USE_NEW_METADATA_MAPPINGS, "true");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getMappings() {
|
||||
return new String[] { "discriminator/SimpleInheritance.hbm.xml" };
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDiscriminatorSubclass() {
|
||||
Session s = openSession();
|
||||
Transaction t = s.beginTransaction();
|
||||
|
||||
Employee mark = new Employee();
|
||||
mark.setId( 1 );
|
||||
mark.setName( "Mark" );
|
||||
mark.setTitle( "internal sales" );
|
||||
mark.setSex( 'M' );
|
||||
|
||||
Customer joe = new Customer();
|
||||
joe.setId( 2 );
|
||||
joe.setName( "Joe" );
|
||||
joe.setComments( "Very demanding" );
|
||||
joe.setSex( 'M' );
|
||||
|
||||
Person yomomma = new Person();
|
||||
yomomma.setId( 3 );
|
||||
yomomma.setName("mum");
|
||||
yomomma.setSex('F');
|
||||
|
||||
s.save(yomomma);
|
||||
s.save(mark);
|
||||
s.save(joe);
|
||||
|
||||
assertEquals( s.createQuery("from java.io.Serializable").list().size(), 0 );
|
||||
|
||||
assertEquals( s.createQuery("from org.hibernate.test.discriminator.Person").list().size(), 3 );
|
||||
assertEquals( s.createQuery("from org.hibernate.test.discriminator.Person p where p.class = org.hibernate.test.discriminator.Person").list().size(), 1 );
|
||||
assertEquals( s.createQuery("from org.hibernate.test.discriminator.Person p where p.class = org.hibernate.test.discriminator.Customer").list().size(), 1 );
|
||||
s.clear();
|
||||
|
||||
List customers = s.createQuery("from org.hibernate.test.discriminator.Customer").list();
|
||||
for ( Object customer : customers ) {
|
||||
Customer c = (Customer) customer;
|
||||
assertEquals( "Very demanding", c.getComments() );
|
||||
}
|
||||
assertEquals( customers.size(), 1 );
|
||||
s.clear();
|
||||
|
||||
mark = (Employee) s.get( Employee.class, mark.getId() );
|
||||
joe = (Customer) s.get( Customer.class, joe.getId() );
|
||||
|
||||
s.delete(mark);
|
||||
s.delete(joe);
|
||||
s.delete(yomomma);
|
||||
assertTrue( s.createQuery("from org.hibernate.test.discriminator.Person").list().isEmpty() );
|
||||
t.commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessAsIncorrectSubclass() {
|
||||
Session s = openSession();
|
||||
s.beginTransaction();
|
||||
Employee e = new Employee();
|
||||
e.setId( 4 );
|
||||
e.setName( "Steve" );
|
||||
e.setSex( 'M' );
|
||||
e.setTitle( "grand poobah" );
|
||||
s.save( e );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.beginTransaction();
|
||||
Customer c = ( Customer ) s.get( Customer.class, e.getId() );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
assertNull( c );
|
||||
|
||||
s = openSession();
|
||||
s.beginTransaction();
|
||||
e = ( Employee ) s.get( Employee.class, e.getId() );
|
||||
c = ( Customer ) s.get( Customer.class, e.getId() );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
assertNotNull( e );
|
||||
assertNull( c );
|
||||
|
||||
s = openSession();
|
||||
s.beginTransaction();
|
||||
s.delete( e );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQuerySubclassAttribute() {
|
||||
Session s = openSession();
|
||||
Transaction t = s.beginTransaction();
|
||||
Person p = new Person();
|
||||
p.setId( 5 );
|
||||
p.setName("Emmanuel");
|
||||
p.setSex('M');
|
||||
s.save( p );
|
||||
Employee q = new Employee();
|
||||
q.setId( 6 );
|
||||
q.setName("Steve");
|
||||
q.setSex('M');
|
||||
q.setTitle("Mr");
|
||||
q.setSalary( new BigDecimal(1000) );
|
||||
s.save( q );
|
||||
|
||||
List result = s.createQuery("from org.hibernate.test.discriminator.Person where salary > 100").list();
|
||||
assertEquals( result.size(), 1 );
|
||||
assertSame( result.get(0), q );
|
||||
|
||||
result = s.createQuery("from org.hibernate.test.discriminator.Person where salary > 100 or name like 'E%'").list();
|
||||
assertEquals( result.size(), 2 );
|
||||
|
||||
result = s.createCriteria(Person.class)
|
||||
.add( Property.forName("salary").gt( new BigDecimal(100) ) )
|
||||
.list();
|
||||
assertEquals( result.size(), 1 );
|
||||
assertSame( result.get(0), q );
|
||||
|
||||
//TODO: make this work:
|
||||
/*result = s.createQuery("select salary from Person where salary > 100").list();
|
||||
assertEquals( result.size(), 1 );
|
||||
assertEquals( result.get(0), new BigDecimal(1000) );*/
|
||||
|
||||
s.delete(p);
|
||||
s.delete(q);
|
||||
t.commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadSuperclassProxyPolymorphicAccess() {
|
||||
Session s = openSession();
|
||||
s.beginTransaction();
|
||||
Employee e = new Employee();
|
||||
e.setId( 7 );
|
||||
e.setName( "Steve" );
|
||||
e.setSex( 'M' );
|
||||
e.setTitle( "grand poobah" );
|
||||
s.save( e );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.beginTransaction();
|
||||
// load the superclass proxy.
|
||||
Person pLoad = ( Person ) s.load( Person.class, new Long( e.getId() ) );
|
||||
assertTrue( pLoad instanceof HibernateProxy);
|
||||
Person pGet = ( Person ) s.get( Person.class, e.getId());
|
||||
Person pQuery = ( Person ) s.createQuery( "from org.hibernate.test.discriminator.Person where id = :id" )
|
||||
.setLong( "id", e.getId() )
|
||||
.uniqueResult();
|
||||
Person pCriteria = ( Person ) s.createCriteria( Person.class )
|
||||
.add( Restrictions.idEq( e.getId() ) )
|
||||
.uniqueResult();
|
||||
// assert that executing the queries polymorphically returns the same proxy
|
||||
assertSame( pLoad, pGet );
|
||||
assertSame( pLoad, pQuery );
|
||||
assertSame( pLoad, pCriteria );
|
||||
|
||||
// assert that the proxy is not an instance of Employee
|
||||
assertFalse( pLoad instanceof Employee );
|
||||
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.beginTransaction();
|
||||
s.delete( e );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLoadSuperclassProxyEvictPolymorphicAccess() {
|
||||
Session s = openSession();
|
||||
s.beginTransaction();
|
||||
Employee e = new Employee();
|
||||
e.setId( 8 );
|
||||
e.setName( "Steve" );
|
||||
e.setSex( 'M' );
|
||||
e.setTitle( "grand poobah" );
|
||||
s.save( e );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.beginTransaction();
|
||||
// load the superclass proxy.
|
||||
Person pLoad = ( Person ) s.load( Person.class, new Long( e.getId() ) );
|
||||
assertTrue( pLoad instanceof HibernateProxy);
|
||||
// evict the proxy
|
||||
s.evict( pLoad );
|
||||
Employee pGet = ( Employee ) s.get( Person.class, e.getId() );
|
||||
Employee pQuery = ( Employee ) s.createQuery( "from org.hibernate.test.discriminator.Person where id = :id" )
|
||||
.setLong( "id", e.getId() )
|
||||
.uniqueResult();
|
||||
Employee pCriteria = ( Employee ) s.createCriteria( Person.class )
|
||||
.add( Restrictions.idEq( e.getId() ) )
|
||||
.uniqueResult();
|
||||
// assert that executing the queries polymorphically returns the same Employee instance
|
||||
assertSame( pGet, pQuery );
|
||||
assertSame( pGet, pCriteria );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
s = openSession();
|
||||
s.beginTransaction();
|
||||
s.delete( e );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue