HHH-6498 HHH-6337 : Updates to support single-table inheritance using new metamodel

This commit is contained in:
Gail Badner 2011-08-11 18:00:28 -07:00
parent 2faeb783a4
commit dc7feab061
11 changed files with 700 additions and 140 deletions

View File

@ -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;
@ -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() );

View File

@ -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 );
}
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 );
}
}

View File

@ -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;

View File

@ -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();

View File

@ -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) {

View File

@ -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;

View File

@ -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();

View File

@ -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( 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() );
for ( AttributeBinding attributeBinding : noInheritanceEntityBinding.getAttributeBindingClosure() ) {
if ( attributeBinding == noInheritanceEntityBinding.getHierarchyDetails().getEntityIdentifier().getValueBinding() ) {
continue;
}
}
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

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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();
}
}