HHH-6337 : Add EntityBinding methods to support single-table inheritance
This commit is contained in:
parent
eb766cc0f7
commit
cb5a74fd51
|
@ -23,8 +23,10 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.binding;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -32,6 +34,7 @@ import org.hibernate.AssertionFailure;
|
|||
import org.hibernate.EntityMode;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.internal.util.Value;
|
||||
import org.hibernate.internal.util.collections.JoinedIterable;
|
||||
import org.hibernate.metamodel.domain.AttributeContainer;
|
||||
import org.hibernate.metamodel.domain.Entity;
|
||||
import org.hibernate.metamodel.domain.PluralAttribute;
|
||||
|
@ -51,6 +54,7 @@ import org.hibernate.tuple.entity.EntityTuplizer;
|
|||
*/
|
||||
public class EntityBinding implements AttributeBindingContainer {
|
||||
private final EntityBinding superEntityBinding;
|
||||
private final List<EntityBinding> subEntityBindings = new ArrayList<EntityBinding>();
|
||||
private final HierarchyDetails hierarchyDetails;
|
||||
|
||||
private Entity entity;
|
||||
|
@ -112,6 +116,7 @@ public class EntityBinding implements AttributeBindingContainer {
|
|||
*/
|
||||
public EntityBinding(EntityBinding superEntityBinding) {
|
||||
this.superEntityBinding = superEntityBinding;
|
||||
this.superEntityBinding.subEntityBindings.add( this );
|
||||
this.hierarchyDetails = superEntityBinding.getHierarchyDetails();
|
||||
}
|
||||
|
||||
|
@ -127,6 +132,38 @@ public class EntityBinding implements AttributeBindingContainer {
|
|||
return superEntityBinding == null;
|
||||
}
|
||||
|
||||
public boolean isPolymorphic() {
|
||||
return superEntityBinding != null ||
|
||||
hierarchyDetails.getEntityDiscriminator() != null ||
|
||||
! subEntityBindings.isEmpty();
|
||||
}
|
||||
|
||||
public boolean hasSubEntityBindings() {
|
||||
return subEntityBindings.size() > 0;
|
||||
}
|
||||
|
||||
public int getSubEntityBindingSpan() {
|
||||
int n = subEntityBindings.size();
|
||||
for ( EntityBinding subEntityBinding : subEntityBindings ) {
|
||||
n += subEntityBinding.getSubEntityBindingSpan();
|
||||
}
|
||||
return n;
|
||||
}
|
||||
/**
|
||||
* Iterate over subclasses in a special 'order', most derived subclasses
|
||||
* first.
|
||||
* @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 );
|
||||
for ( EntityBinding subEntityBinding : subEntityBindings ) {
|
||||
subclassIterables.add( subEntityBinding.getSubEntityBindingClosure() );
|
||||
}
|
||||
subclassIterables.add( subEntityBindings );
|
||||
return new JoinedIterable<EntityBinding>( subclassIterables );
|
||||
}
|
||||
|
||||
public Entity getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
@ -457,9 +494,10 @@ public class EntityBinding implements AttributeBindingContainer {
|
|||
* @return The number of attribute bindings
|
||||
*/
|
||||
public int getAttributeBindingClosureSpan() {
|
||||
// TODO: fix this after HHH-6337 is fixed; for now just return size of attributeBindingMap
|
||||
// if this is not a root, then need to include the superclass attribute bindings
|
||||
return attributeBindingMap.size();
|
||||
// TODO: update account for join attribute bindings
|
||||
return superEntityBinding != null ?
|
||||
superEntityBinding.getAttributeBindingClosureSpan() + attributeBindingMap.size() :
|
||||
attributeBindingMap.size();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -470,8 +508,17 @@ public class EntityBinding implements AttributeBindingContainer {
|
|||
* @return The attribute bindings.
|
||||
*/
|
||||
public Iterable<AttributeBinding> getAttributeBindingClosure() {
|
||||
// TODO: fix this after HHH-6337 is fixed. for now, just return attributeBindings
|
||||
// if this is not a root, then need to include the superclass attribute bindings
|
||||
return attributeBindings();
|
||||
// TODO: update size to account for joins
|
||||
Iterable<AttributeBinding> iterable;
|
||||
if ( superEntityBinding != null ) {
|
||||
List<Iterable<AttributeBinding>> iterables = new ArrayList<Iterable<AttributeBinding>>( 2 );
|
||||
iterables.add( superEntityBinding.getAttributeBindingClosure() );
|
||||
iterables.add( attributeBindings() );
|
||||
iterable = new JoinedIterable<AttributeBinding>( iterables );
|
||||
}
|
||||
else {
|
||||
iterable = attributeBindings();
|
||||
}
|
||||
return iterable;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,9 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.source.annotations.entity;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import javax.persistence.DiscriminatorColumn;
|
||||
import javax.persistence.DiscriminatorType;
|
||||
import javax.persistence.DiscriminatorValue;
|
||||
|
@ -34,6 +37,7 @@ import org.junit.Test;
|
|||
|
||||
import org.hibernate.annotations.DiscriminatorFormula;
|
||||
import org.hibernate.annotations.DiscriminatorOptions;
|
||||
import org.hibernate.metamodel.binding.AttributeBinding;
|
||||
import org.hibernate.metamodel.binding.EntityBinding;
|
||||
import org.hibernate.metamodel.binding.EntityDiscriminator;
|
||||
import org.hibernate.metamodel.relational.DerivedValue;
|
||||
|
@ -55,13 +59,14 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
public void testNoInheritance() {
|
||||
EntityBinding entityBinding = getEntityBinding( SingleEntity.class );
|
||||
assertNull( entityBinding.getHierarchyDetails().getEntityDiscriminator() );
|
||||
assertFalse( entityBinding.isPolymorphic() );
|
||||
}
|
||||
|
||||
@Test
|
||||
@Resources(annotatedClasses = { RootOfSingleTableInheritance.class, SubclassOfSingleTableInheritance.class })
|
||||
public void testDiscriminatorValue() {
|
||||
EntityBinding entityBinding = getEntityBinding( SubclassOfSingleTableInheritance.class );
|
||||
assertEquals( "Wrong discriminator value", "foo", entityBinding.getDiscriminatorMatchValue() );
|
||||
assertEquals( "Wrong discriminator value", "foo1", entityBinding.getDiscriminatorMatchValue() );
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -101,6 +106,169 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
assertSame( rootEntityBinding, getRootEntityBinding( RootOfSingleTableInheritance.class ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
@Resources(annotatedClasses = {
|
||||
SubclassOfSingleTableInheritance.class,
|
||||
SingleEntity.class,
|
||||
RootOfSingleTableInheritance.class,
|
||||
OtherSubclassOfSingleTableInheritance.class,
|
||||
SubclassOfSubclassOfSingleTableInheritance.class
|
||||
})
|
||||
public void testNoPolymorphism() {
|
||||
EntityBinding noInheritanceEntityBinding = getEntityBinding( SingleEntity.class );
|
||||
assertTrue( "SingleEntity should be a root entity", noInheritanceEntityBinding.isRoot() );
|
||||
assertNull( noInheritanceEntityBinding.getSuperEntityBinding() );
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Resources(annotatedClasses = {
|
||||
SubclassOfSingleTableInheritance.class,
|
||||
SingleEntity.class,
|
||||
RootOfSingleTableInheritance.class,
|
||||
OtherSubclassOfSingleTableInheritance.class,
|
||||
SubclassOfSubclassOfSingleTableInheritance.class
|
||||
})
|
||||
public void testRootPolymporhism() {
|
||||
EntityBinding rootEntityBinding = getEntityBinding( RootOfSingleTableInheritance.class );
|
||||
EntityBinding subclassEntityBinding = getEntityBinding( SubclassOfSingleTableInheritance.class );
|
||||
EntityBinding otherSubclassEntityBinding = getEntityBinding( OtherSubclassOfSingleTableInheritance.class );
|
||||
EntityBinding subclassOfSubclassEntityBinding = getEntityBinding( SubclassOfSubclassOfSingleTableInheritance.class );
|
||||
|
||||
assertTrue( rootEntityBinding.isRoot() );
|
||||
assertNull( rootEntityBinding.getDiscriminatorMatchValue() );
|
||||
assertNull( rootEntityBinding.getSuperEntityBinding() );
|
||||
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 );
|
||||
}
|
||||
assertEquals( 3, subEntityBindings.size() );
|
||||
assertTrue( subEntityBindings.contains( subclassEntityBinding ) );
|
||||
assertTrue( subEntityBindings.contains( otherSubclassEntityBinding ) );
|
||||
assertTrue( subEntityBindings.contains( subclassOfSubclassEntityBinding ) );
|
||||
assertEquals( 1, rootEntityBinding.getAttributeBindingClosureSpan() );
|
||||
Set<String> attributeNames = new HashSet<String>();
|
||||
for ( AttributeBinding attributeBinding : rootEntityBinding.getAttributeBindingClosure() ) {
|
||||
attributeNames.add( attributeBinding.getAttribute().getName() );
|
||||
}
|
||||
assertEquals( 1, attributeNames.size() );
|
||||
assertTrue( attributeNames.contains( "id" ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
@Resources(annotatedClasses = {
|
||||
SubclassOfSingleTableInheritance.class,
|
||||
SingleEntity.class,
|
||||
RootOfSingleTableInheritance.class,
|
||||
OtherSubclassOfSingleTableInheritance.class,
|
||||
SubclassOfSubclassOfSingleTableInheritance.class
|
||||
})
|
||||
public void testLeafSubclassOfRoot() {
|
||||
EntityBinding rootEntityBinding = getEntityBinding( RootOfSingleTableInheritance.class );
|
||||
EntityBinding subclassEntityBinding = getEntityBinding( SubclassOfSingleTableInheritance.class );
|
||||
EntityBinding otherSubclassEntityBinding = getEntityBinding( OtherSubclassOfSingleTableInheritance.class );
|
||||
EntityBinding subclassOfSubclassEntityBinding = getEntityBinding( SubclassOfSubclassOfSingleTableInheritance.class );
|
||||
|
||||
assertEquals( "Wrong discriminator value", "foo2", otherSubclassEntityBinding.getDiscriminatorMatchValue() );
|
||||
assertFalse( otherSubclassEntityBinding.isRoot() );
|
||||
assertSame( rootEntityBinding, otherSubclassEntityBinding.getSuperEntityBinding() );
|
||||
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( 2, attributeNames.size() );
|
||||
assertTrue( attributeNames.contains( "id" ) );
|
||||
assertTrue( attributeNames.contains( "otherName" ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
@Resources(annotatedClasses = {
|
||||
SubclassOfSingleTableInheritance.class,
|
||||
SingleEntity.class,
|
||||
RootOfSingleTableInheritance.class,
|
||||
OtherSubclassOfSingleTableInheritance.class,
|
||||
SubclassOfSubclassOfSingleTableInheritance.class
|
||||
})
|
||||
public void testNonLeafSubclassOfRootPolymporhism() {
|
||||
EntityBinding rootEntityBinding = getEntityBinding( RootOfSingleTableInheritance.class );
|
||||
EntityBinding subclassEntityBinding = getEntityBinding( SubclassOfSingleTableInheritance.class );
|
||||
EntityBinding otherSubclassEntityBinding = getEntityBinding( OtherSubclassOfSingleTableInheritance.class );
|
||||
EntityBinding subclassOfSubclassEntityBinding = getEntityBinding( SubclassOfSubclassOfSingleTableInheritance.class );
|
||||
|
||||
assertEquals( "Wrong discriminator value", "foo1", subclassEntityBinding.getDiscriminatorMatchValue() );
|
||||
assertFalse( subclassEntityBinding.isRoot() );
|
||||
assertSame( rootEntityBinding, subclassEntityBinding.getSuperEntityBinding() );
|
||||
assertSame( rootEntityBinding, getRootEntityBinding( SubclassOfSingleTableInheritance.class ) );
|
||||
assertTrue( subclassEntityBinding.isPolymorphic() );
|
||||
assertTrue( subclassEntityBinding.hasSubEntityBindings() );
|
||||
assertEquals( 1, subclassEntityBinding.getSubEntityBindingSpan() );
|
||||
Iterator<EntityBinding> itSubEntityBindings = subclassEntityBinding.getSubEntityBindingClosure().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() );
|
||||
}
|
||||
assertEquals( 2, attributeNames.size() );
|
||||
assertTrue( attributeNames.contains( "id" ) );
|
||||
assertTrue( attributeNames.contains( "name" ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
@Resources(annotatedClasses = {
|
||||
SubclassOfSingleTableInheritance.class,
|
||||
SingleEntity.class,
|
||||
RootOfSingleTableInheritance.class,
|
||||
OtherSubclassOfSingleTableInheritance.class,
|
||||
SubclassOfSubclassOfSingleTableInheritance.class
|
||||
})
|
||||
public void testLeafSubclassOfSubclassOfRootPolymporhism() {
|
||||
EntityBinding rootEntityBinding = getEntityBinding( RootOfSingleTableInheritance.class );
|
||||
EntityBinding subclassEntityBinding = getEntityBinding( SubclassOfSingleTableInheritance.class );
|
||||
EntityBinding otherSubclassEntityBinding = getEntityBinding( OtherSubclassOfSingleTableInheritance.class );
|
||||
EntityBinding subclassOfSubclassEntityBinding = getEntityBinding( SubclassOfSubclassOfSingleTableInheritance.class );
|
||||
|
||||
assertEquals( "Wrong discriminator value", "foo1_1", subclassOfSubclassEntityBinding.getDiscriminatorMatchValue() );
|
||||
assertFalse( subclassOfSubclassEntityBinding.isRoot() );
|
||||
assertSame( subclassEntityBinding, subclassOfSubclassEntityBinding.getSuperEntityBinding() );
|
||||
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( 3, attributeNames.size() );
|
||||
assertTrue( attributeNames.contains( "id" ) );
|
||||
assertTrue( attributeNames.contains( "name" ) );
|
||||
assertTrue( attributeNames.contains( "otherOtherName" ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
@Resources(annotatedClasses = { RootOfSingleTableInheritance.class, SubclassOfSingleTableInheritance.class })
|
||||
public void testDefaultDiscriminatorOptions() {
|
||||
|
@ -150,8 +318,21 @@ public class InheritanceBindingTest extends BaseAnnotationBindingTestCase {
|
|||
}
|
||||
|
||||
@Entity
|
||||
@DiscriminatorValue("foo")
|
||||
@DiscriminatorValue("foo1")
|
||||
public class SubclassOfSingleTableInheritance extends RootOfSingleTableInheritance {
|
||||
private String name;
|
||||
}
|
||||
|
||||
@Entity
|
||||
@DiscriminatorValue("foo2")
|
||||
public class OtherSubclassOfSingleTableInheritance extends RootOfSingleTableInheritance {
|
||||
private String otherName;
|
||||
}
|
||||
|
||||
@Entity
|
||||
@DiscriminatorValue("foo1_1")
|
||||
public class SubclassOfSubclassOfSingleTableInheritance extends SubclassOfSingleTableInheritance {
|
||||
private String otherOtherName;
|
||||
}
|
||||
|
||||
@Entity
|
||||
|
|
Loading…
Reference in New Issue