Fix UnionSublcass polymorphic associations
This commit is contained in:
parent
5b82cd59d7
commit
01b24089c2
|
@ -617,7 +617,8 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
||||||
|
|
||||||
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() );
|
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() );
|
||||||
|
|
||||||
final TableReference primaryTableReference = entityPartDescriptor.getEntityMappingType()
|
final EntityMappingType entityMappingType = entityPartDescriptor.getEntityMappingType();
|
||||||
|
final TableReference primaryTableReference = entityMappingType
|
||||||
.createPrimaryTableReference(
|
.createPrimaryTableReference(
|
||||||
sqlAliasBase,
|
sqlAliasBase,
|
||||||
sqlExpressionResolver,
|
sqlExpressionResolver,
|
||||||
|
@ -630,9 +631,9 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
|
||||||
lockMode,
|
lockMode,
|
||||||
primaryTableReference,
|
primaryTableReference,
|
||||||
sqlAliasBase,
|
sqlAliasBase,
|
||||||
(tableExpression) -> entityPartDescriptor.getEntityMappingType()
|
(tableExpression) -> entityMappingType
|
||||||
.containsTableReference( tableExpression ),
|
.containsTableReference( tableExpression ),
|
||||||
(tableExpression, tg) -> entityPartDescriptor.getEntityMappingType().createTableReferenceJoin(
|
(tableExpression, tg) -> entityMappingType.createTableReferenceJoin(
|
||||||
tableExpression,
|
tableExpression,
|
||||||
sqlAliasBase,
|
sqlAliasBase,
|
||||||
primaryTableReference,
|
primaryTableReference,
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.metamodel.mapping.internal;
|
package org.hibernate.metamodel.mapping.internal;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
@ -163,10 +162,7 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
||||||
SqlAstJoinType sqlAstJoinType,
|
SqlAstJoinType sqlAstJoinType,
|
||||||
SqlExpressionResolver sqlExpressionResolver,
|
SqlExpressionResolver sqlExpressionResolver,
|
||||||
SqlAstCreationContext creationContext) {
|
SqlAstCreationContext creationContext) {
|
||||||
final String rhsTableExpression = rhs.getTableExpression();
|
if ( lhs.getTableReference( keyColumnContainingTable ) != null ) {
|
||||||
final String lhsTableExpression = lhs.getTableExpression();
|
|
||||||
if ( lhsTableExpression.equals( keyColumnContainingTable ) ) {
|
|
||||||
assert rhsTableExpression.equals( targetColumnContainingTable );
|
|
||||||
return new ComparisonPredicate(
|
return new ComparisonPredicate(
|
||||||
new ColumnReference(
|
new ColumnReference(
|
||||||
lhs,
|
lhs,
|
||||||
|
@ -184,7 +180,6 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert rhsTableExpression.equals( keyColumnContainingTable );
|
|
||||||
return new ComparisonPredicate(
|
return new ComparisonPredicate(
|
||||||
new ColumnReference(
|
new ColumnReference(
|
||||||
lhs,
|
lhs,
|
||||||
|
|
|
@ -51,6 +51,7 @@ import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||||
import org.hibernate.sql.ast.tree.from.UnionTableGroup;
|
import org.hibernate.sql.ast.tree.from.UnionTableGroup;
|
||||||
|
import org.hibernate.sql.ast.tree.from.UnionTableReference;
|
||||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||||
import org.hibernate.type.StandardBasicTypes;
|
import org.hibernate.type.StandardBasicTypes;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
@ -233,13 +234,20 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
|
||||||
SqlAstCreationContext creationContext) {
|
SqlAstCreationContext creationContext) {
|
||||||
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() );
|
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() );
|
||||||
|
|
||||||
final TableReference tableReference = new TableReference(
|
final TableReference tableReference = resolvePrimaryTableReference(sqlAliasBase);
|
||||||
|
|
||||||
|
return new UnionTableGroup( navigablePath, tableReference, this );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected TableReference resolvePrimaryTableReference(SqlAliasBase sqlAliasBase) {
|
||||||
|
return new UnionTableReference(
|
||||||
getTableName(),
|
getTableName(),
|
||||||
|
subclassSpaces,
|
||||||
sqlAliasBase.generateNewAlias(),
|
sqlAliasBase.generateNewAlias(),
|
||||||
false,
|
false,
|
||||||
getFactory()
|
getFactory()
|
||||||
);
|
);
|
||||||
return new UnionTableGroup( navigablePath, tableReference, this );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -26,7 +26,7 @@ public abstract class AbstractColumnReferenceQualifier implements ColumnReferenc
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TableReference resolveTableReference(String tableExpression, Supplier<TableReference> creator) {
|
public TableReference resolveTableReference(String tableExpression, Supplier<TableReference> creator) {
|
||||||
final TableReference existing = resolveTableReferenceInternal( tableExpression );
|
final TableReference existing = getTableReferenceInternal( tableExpression );
|
||||||
if ( existing != null ) {
|
if ( existing != null ) {
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ public abstract class AbstractColumnReferenceQualifier implements ColumnReferenc
|
||||||
public TableReference resolveTableReference(String tableExpression) {
|
public TableReference resolveTableReference(String tableExpression) {
|
||||||
assert tableExpression != null;
|
assert tableExpression != null;
|
||||||
|
|
||||||
final TableReference tableReference = resolveTableReferenceInternal( tableExpression );
|
final TableReference tableReference = getTableReferenceInternal( tableExpression );
|
||||||
if ( tableReference == null ) {
|
if ( tableReference == null ) {
|
||||||
throw new IllegalStateException( "Could not resolve binding for table `" + tableExpression + "`" );
|
throw new IllegalStateException( "Could not resolve binding for table `" + tableExpression + "`" );
|
||||||
}
|
}
|
||||||
|
@ -48,16 +48,16 @@ public abstract class AbstractColumnReferenceQualifier implements ColumnReferenc
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TableReference getTableReference(String tableExpression) {
|
public TableReference getTableReference(String tableExpression) {
|
||||||
return resolveTableReferenceInternal( tableExpression );
|
return getTableReferenceInternal( tableExpression );
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TableReference resolveTableReferenceInternal(String tableExpression) {
|
protected TableReference getTableReferenceInternal(String tableExpression) {
|
||||||
if ( getPrimaryTableReference().getTableExpression().equals( tableExpression ) ) {
|
if ( getPrimaryTableReference().getTableReference( tableExpression ) != null) {
|
||||||
return getPrimaryTableReference();
|
return getPrimaryTableReference();
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( TableReferenceJoin tableJoin : getTableReferenceJoins() ) {
|
for ( TableReferenceJoin tableJoin : getTableReferenceJoins() ) {
|
||||||
if ( tableJoin.getJoinedTableReference().getTableExpression().equals( tableExpression ) ) {
|
if ( tableJoin.getJoinedTableReference().getTableReference( tableExpression ) != null) {
|
||||||
return tableJoin.getJoinedTableReference();
|
return tableJoin.getJoinedTableReference();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,12 +104,7 @@ public abstract class AbstractTableGroup extends AbstractColumnReferenceQualifie
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTableGroupJoins(Set<TableGroupJoin> joins) {
|
public void setTableGroupJoins(Set<TableGroupJoin> joins) {
|
||||||
if ( tableGroupJoins == null ) {
|
tableGroupJoins = new HashSet<>( joins );
|
||||||
tableGroupJoins = new HashSet<>( joins );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
tableGroupJoins.addAll( joins );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -75,12 +75,7 @@ public class CompositeTableGroup implements VirtualTableGroup {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTableGroupJoins(Set<TableGroupJoin> joins) {
|
public void setTableGroupJoins(Set<TableGroupJoin> joins) {
|
||||||
if ( tableGroupJoins == null ) {
|
tableGroupJoins = new HashSet<>( joins );
|
||||||
tableGroupJoins = new HashSet<>( joins );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
tableGroupJoins.addAll( joins );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -94,8 +94,8 @@ public class StandardTableGroup extends AbstractTableGroup {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TableReference resolveTableReferenceInternal(String tableExpression) {
|
public TableReference getTableReferenceInternal(String tableExpression) {
|
||||||
final TableReference tableReference = super.resolveTableReferenceInternal( tableExpression );
|
final TableReference tableReference = super.getTableReferenceInternal( tableExpression );
|
||||||
if ( tableReference != null ) {
|
if ( tableReference != null ) {
|
||||||
return tableReference;
|
return tableReference;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ public class StandardTableGroup extends AbstractTableGroup {
|
||||||
for ( int i = 0; i < tableJoins.size(); i++ ) {
|
for ( int i = 0; i < tableJoins.size(); i++ ) {
|
||||||
final TableReferenceJoin join = tableJoins.get( i );
|
final TableReferenceJoin join = tableJoins.get( i );
|
||||||
assert join != null;
|
assert join != null;
|
||||||
if ( join.getJoinedTableReference().getTableExpression().equals( tableExpression ) ) {
|
if ( join.getJoinedTableReference().getTableReference( tableExpression ) != null ) {
|
||||||
return join.getJoinedTableReference();
|
return join.getJoinedTableReference();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ public class StandardTableGroup extends AbstractTableGroup {
|
||||||
|
|
||||||
for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) {
|
for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) {
|
||||||
final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference();
|
final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference();
|
||||||
if ( primaryTableReference.getTableExpression().equals( tableExpression ) ) {
|
if ( primaryTableReference.getTableReference( tableExpression ) != null ) {
|
||||||
return primaryTableReference;
|
return primaryTableReference;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ public interface TableGroup extends SqlAstNode, ColumnReferenceQualifier, SqmPat
|
||||||
void applyAffectedTableNames(Consumer<String> nameCollector);
|
void applyAffectedTableNames(Consumer<String> nameCollector);
|
||||||
|
|
||||||
TableReference getPrimaryTableReference();
|
TableReference getPrimaryTableReference();
|
||||||
|
|
||||||
List<TableReferenceJoin> getTableReferenceJoins();
|
List<TableReferenceJoin> getTableReferenceJoins();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -61,7 +61,7 @@ public class TableReference implements SqlAstNode, ColumnReferenceQualifier {
|
||||||
if ( tableExpression.equals( getTableExpression() ) ) {
|
if ( tableExpression.equals( getTableExpression() ) ) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
return null;
|
throw new IllegalStateException( "Could not resolve binding for table `" + tableExpression + "`" );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.sql.ast.tree.from;
|
package org.hibernate.sql.ast.tree.from;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
@ -23,6 +24,7 @@ import org.hibernate.query.NavigablePath;
|
||||||
*/
|
*/
|
||||||
public class UnionTableGroup implements VirtualTableGroup {
|
public class UnionTableGroup implements VirtualTableGroup {
|
||||||
private final NavigablePath navigablePath;
|
private final NavigablePath navigablePath;
|
||||||
|
private Set<TableGroupJoin> tableGroupJoins;
|
||||||
|
|
||||||
private final UnionSubclassEntityPersister modelPart;
|
private final UnionSubclassEntityPersister modelPart;
|
||||||
private final TableReference tableReference;
|
private final TableReference tableReference;
|
||||||
|
@ -63,24 +65,32 @@ public class UnionTableGroup implements VirtualTableGroup {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<TableGroupJoin> getTableGroupJoins() {
|
public Set<TableGroupJoin> getTableGroupJoins() {
|
||||||
return Collections.emptySet();
|
return tableGroupJoins == null ? Collections.emptySet() : Collections.unmodifiableSet( tableGroupJoins );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasTableGroupJoins() {
|
public boolean hasTableGroupJoins() {
|
||||||
return false;
|
return tableGroupJoins != null && !tableGroupJoins.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setTableGroupJoins(Set<TableGroupJoin> joins) {
|
public void setTableGroupJoins(Set<TableGroupJoin> joins) {
|
||||||
|
tableGroupJoins = new HashSet<>( joins );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTableGroupJoin(TableGroupJoin join) {
|
public void addTableGroupJoin(TableGroupJoin join) {
|
||||||
|
if ( tableGroupJoins == null ) {
|
||||||
|
tableGroupJoins = new HashSet<>();
|
||||||
|
}
|
||||||
|
tableGroupJoins.add( join );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
|
||||||
|
if ( tableGroupJoins != null ) {
|
||||||
|
tableGroupJoins.forEach( consumer );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.sql.ast.tree.from;
|
||||||
|
|
||||||
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Andrea Boriero
|
||||||
|
*/
|
||||||
|
public class UnionTableReference extends TableReference {
|
||||||
|
private final String[] subclassTableSpaceExpressions;
|
||||||
|
|
||||||
|
public UnionTableReference(
|
||||||
|
String unionTableExpression,
|
||||||
|
String[] subclassTableSpaceExpressions,
|
||||||
|
String identificationVariable,
|
||||||
|
boolean isOptional,
|
||||||
|
SessionFactoryImplementor sessionFactory) {
|
||||||
|
super( unionTableExpression, identificationVariable, isOptional, sessionFactory );
|
||||||
|
|
||||||
|
this.subclassTableSpaceExpressions = subclassTableSpaceExpressions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TableReference resolveTableReference(String tableExpression) {
|
||||||
|
if ( hasTableExpression( tableExpression ) ) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
throw new IllegalStateException( "Could not resolve binding for table `" + tableExpression + "`" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TableReference getTableReference(String tableExpression) {
|
||||||
|
if ( hasTableExpression( tableExpression ) ) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasTableExpression(String tableExpression) {
|
||||||
|
if ( tableExpression.equals( getTableExpression() ) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for ( String expression : subclassTableSpaceExpressions ) {
|
||||||
|
if ( tableExpression.equals( expression ) ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -128,8 +128,8 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
|
||||||
for ( int i = 0; i < identifierInitializers.size(); i++ ) {
|
for ( int i = 0; i < identifierInitializers.size(); i++ ) {
|
||||||
final Initializer existing = identifierInitializers.get( i );
|
final Initializer existing = identifierInitializers.get( i );
|
||||||
if ( existing.getNavigablePath().equals( navigablePath )
|
if ( existing.getNavigablePath().equals( navigablePath )
|
||||||
&& fetchedModelPart.getNavigableRole().equals(
|
&& fetchedModelPart.getNavigableRole()
|
||||||
existing.getInitializedPart().getNavigableRole() ) ) {
|
.equals( existing.getInitializedPart().getNavigableRole() ) ) {
|
||||||
return existing;
|
return existing;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,297 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.orm.test.inheritance.discriminator;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.DiscriminatorColumn;
|
||||||
|
import javax.persistence.DiscriminatorType;
|
||||||
|
import javax.persistence.DiscriminatorValue;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Inheritance;
|
||||||
|
import javax.persistence.InheritanceType;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
|
||||||
|
import org.hibernate.testing.TestForIssue;
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.core.Is.is;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Davide D'Alto
|
||||||
|
*/
|
||||||
|
@TestForIssue(jiraKey = "HHH-12332")
|
||||||
|
@DomainModel(
|
||||||
|
annotatedClasses = {
|
||||||
|
TablePerClassInheritanceTest.Person.class,
|
||||||
|
TablePerClassInheritanceTest.Child.class,
|
||||||
|
TablePerClassInheritanceTest.Man.class,
|
||||||
|
TablePerClassInheritanceTest.Woman.class
|
||||||
|
}
|
||||||
|
)
|
||||||
|
@SessionFactory
|
||||||
|
public class TablePerClassInheritanceTest {
|
||||||
|
private final Man john = new Man( "John", "Riding Roller Coasters" );
|
||||||
|
private final Woman jane = new Woman( "Jane", "Hippotherapist" );
|
||||||
|
private final Child susan = new Child( "Susan", "Super Mario retro Mushroom" );
|
||||||
|
private final Child mark = new Child( "Mark", "Fidget Spinner" );
|
||||||
|
private final List<Child> children = new ArrayList<>( Arrays.asList( susan, mark ) );
|
||||||
|
private final List<Person> familyMembers = Arrays.asList( john, jane, susan, mark );
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setUp(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
jane.setHusband( john );
|
||||||
|
jane.setChildren( children );
|
||||||
|
|
||||||
|
john.setWife( jane );
|
||||||
|
john.setChildren( children );
|
||||||
|
|
||||||
|
for ( Child child : children ) {
|
||||||
|
child.setFather( john );
|
||||||
|
child.setMother( jane );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( Person person : familyMembers ) {
|
||||||
|
session.persist( person );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void tearDown(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(
|
||||||
|
session -> {
|
||||||
|
List<Person> people = session.createQuery( "FROM Person p", Person.class ).getResultList();
|
||||||
|
people.forEach( person -> session.delete( person ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSelectHierarchyRoot(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
List<Person> people = session.createQuery( "FROM Person p", Person.class ).getResultList();
|
||||||
|
assertThat( people.size(), is( familyMembers.size() ) );
|
||||||
|
for ( Person person : people ) {
|
||||||
|
if ( person instanceof Man ) {
|
||||||
|
assertThat( ( (Man) person ).getHobby(), is( john.getHobby() ) );
|
||||||
|
}
|
||||||
|
else if ( person instanceof Woman ) {
|
||||||
|
assertThat( ( (Woman) person ).getJob(), is( jane.getJob() ) );
|
||||||
|
}
|
||||||
|
else if ( person instanceof Child ) {
|
||||||
|
if ( person.getName().equals( "Susan" ) ) {
|
||||||
|
assertThat( ( (Child) person ).getFavouriteToy(), is( susan.getFavouriteToy() ) );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assertThat( ( (Child) person ).getFavouriteToy(), is( mark.getFavouriteToy() ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fail( "Unexpected result: " + person );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSelectHierarchyLeaf(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
List<Man> men = session.createQuery( "FROM Man m", Man.class ).getResultList();
|
||||||
|
for ( Man man : men ) {
|
||||||
|
assertThat( man.getHobby(), is( john.getHobby() ) );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetHierarchyLeaf(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( session -> {
|
||||||
|
Man man = session.get( Man.class, "John" );
|
||||||
|
assertThat( man.getHobby(), is( john.getHobby() ) );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Entity(name = "Person")
|
||||||
|
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
|
||||||
|
@DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING)
|
||||||
|
public static class Person {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
|
||||||
|
public Person() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Person(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Child")
|
||||||
|
@DiscriminatorValue("CHILD")
|
||||||
|
public static class Child extends Person {
|
||||||
|
|
||||||
|
private String favouriteToy;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
private Woman mother;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
private Man father;
|
||||||
|
|
||||||
|
public Child() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Child(String name, String favouriteToy) {
|
||||||
|
super( name );
|
||||||
|
this.favouriteToy = favouriteToy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFavouriteToy() {
|
||||||
|
return favouriteToy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFavouriteToy(String favouriteToy) {
|
||||||
|
this.favouriteToy = favouriteToy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Man getFather() {
|
||||||
|
return father;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFather(Man father) {
|
||||||
|
this.father = father;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Woman getMother() {
|
||||||
|
return mother;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMother(Woman mother) {
|
||||||
|
this.mother = mother;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Man")
|
||||||
|
@DiscriminatorValue("MAN")
|
||||||
|
public static class Man extends Person {
|
||||||
|
|
||||||
|
private String hobby;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
private Woman wife;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "father")
|
||||||
|
private List<Child> children = new ArrayList<>();
|
||||||
|
|
||||||
|
public Man() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Man(String name, String hobby) {
|
||||||
|
super( name );
|
||||||
|
this.hobby = hobby;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getHobby() {
|
||||||
|
return hobby;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHobby(String hobby) {
|
||||||
|
this.hobby = hobby;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Woman getWife() {
|
||||||
|
return wife;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWife(Woman wife) {
|
||||||
|
this.wife = wife;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Child> getChildren() {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChildren(List<Child> children) {
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Woman")
|
||||||
|
@DiscriminatorValue("WOMAN")
|
||||||
|
public static class Woman extends Person {
|
||||||
|
|
||||||
|
private String job;
|
||||||
|
|
||||||
|
@OneToOne
|
||||||
|
private Man husband;
|
||||||
|
|
||||||
|
@OneToMany(mappedBy = "mother")
|
||||||
|
private List<Child> children = new ArrayList<>();
|
||||||
|
|
||||||
|
public Woman() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Woman(String name, String job) {
|
||||||
|
super( name );
|
||||||
|
this.job = job;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJob() {
|
||||||
|
return job;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setJob(String job) {
|
||||||
|
this.job = job;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Man getHusband() {
|
||||||
|
return husband;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHusband(Man husband) {
|
||||||
|
this.husband = husband;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Child> getChildren() {
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChildren(List<Child> children) {
|
||||||
|
this.children = children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue