HHH-17102 Fix @SqlResultSetMapping issue for joined inheritance entity result
This commit is contained in:
parent
0ff7325e37
commit
b89ef5dd04
|
@ -276,11 +276,7 @@ public class SqlResultSetMappingDescriptor implements NamedResultSetMappingDescr
|
|||
String discriminatorColumn,
|
||||
NavigablePath entityPath) {
|
||||
final EntityDiscriminatorMapping discriminatorMapping = entityMapping.getDiscriminatorMapping();
|
||||
if ( discriminatorMapping == null ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( discriminatorColumn == null ) {
|
||||
if ( discriminatorMapping == null || discriminatorColumn == null || !entityMapping.hasSubclasses() ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -178,10 +178,10 @@ public class CaseStatementDiscriminatorMappingImpl extends AbstractDiscriminator
|
|||
|
||||
@Override
|
||||
public String getContainingTableExpression() {
|
||||
throw new UnsupportedOperationException();
|
||||
// throw new UnsupportedOperationException();
|
||||
// // this *should* only be used to create the sql-expression key, so just
|
||||
// // using the primary table expr should be fine
|
||||
// return entityDescriptor.getRootTableName();
|
||||
return getEntityDescriptor().getMappedTableDetails().getTableName();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -14,11 +14,14 @@ import org.hibernate.metamodel.mapping.MappingType;
|
|||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
import org.hibernate.type.BasicType;
|
||||
|
||||
import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -80,7 +83,15 @@ public class ExplicitColumnDiscriminatorMappingImpl extends AbstractDiscriminato
|
|||
SqlAstCreationState creationState) {
|
||||
final SqlExpressionResolver expressionResolver = creationState.getSqlExpressionResolver();
|
||||
final TableReference tableReference = tableGroup.resolveTableReference( navigablePath, tableExpression );
|
||||
return expressionResolver.resolveSqlExpression( tableReference, this );
|
||||
|
||||
return expressionResolver.resolveSqlExpression(
|
||||
createColumnReferenceKey(
|
||||
tableGroup.getPrimaryTableReference(),
|
||||
getSelectionExpression(),
|
||||
jdbcMappingToUse
|
||||
),
|
||||
processingState -> new ColumnReference( tableReference, this )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -59,7 +59,7 @@ public class ResultMementoEntityJpa implements ResultMementoEntity, FetchMemento
|
|||
ResultSetMappingResolutionContext context) {
|
||||
final EntityDiscriminatorMapping discriminatorMapping = entityDescriptor.getDiscriminatorMapping();
|
||||
final BasicValuedFetchBuilder discriminatorFetchBuilder;
|
||||
if ( discriminatorMapping == null ) {
|
||||
if ( discriminatorMapping == null || !entityDescriptor.hasSubclasses() ) {
|
||||
assert discriminatorMemento == null;
|
||||
discriminatorFetchBuilder = null;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,8 @@ import java.util.function.BiFunction;
|
|||
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
|
||||
import org.hibernate.query.results.ResultsHelper;
|
||||
import org.hibernate.metamodel.mapping.DiscriminatorMapping;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.spi.NavigablePath;
|
||||
import org.hibernate.query.results.BasicValuedFetchBuilder;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
|
@ -112,9 +113,17 @@ public class CompleteFetchBuilderBasicPart implements CompleteFetchBuilder, Basi
|
|||
|
||||
final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition );
|
||||
|
||||
final JdbcMapping jdbcMapping;
|
||||
if ( referencedModelPart instanceof DiscriminatorMapping ) {
|
||||
jdbcMapping = ( (DiscriminatorMapping) referencedModelPart ).getUnderlyingJdbcMapping();
|
||||
}
|
||||
else {
|
||||
jdbcMapping = referencedModelPart.getJdbcMapping();
|
||||
}
|
||||
|
||||
// we just care about the registration here. The ModelPart will find it later
|
||||
creationStateImpl.resolveSqlExpression(
|
||||
createColumnReferenceKey( tableReference, referencedModelPart ),
|
||||
createColumnReferenceKey( tableReference, referencedModelPart.getSelectablePath(), jdbcMapping ),
|
||||
processingState -> new ResultSetMappingSqlSelection( valuesArrayPosition, referencedModelPart )
|
||||
);
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ public class CompleteResultBuilderEntityJpa implements CompleteResultBuilderEnti
|
|||
}
|
||||
else {
|
||||
// discriminated
|
||||
assert discriminatorFetchBuilder != null;
|
||||
assert !entityDescriptor.hasSubclasses() || discriminatorFetchBuilder != null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* 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.query.resultmapping;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.JiraKey;
|
||||
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 jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EntityResult;
|
||||
import jakarta.persistence.FieldResult;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Inheritance;
|
||||
import jakarta.persistence.InheritanceType;
|
||||
import jakarta.persistence.NamedNativeQuery;
|
||||
import jakarta.persistence.SqlResultSetMapping;
|
||||
import jakarta.persistence.Table;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
@DomainModel( annotatedClasses = {
|
||||
InheritanceTests.Parent.class,
|
||||
InheritanceTests.Child.class
|
||||
} )
|
||||
@SessionFactory
|
||||
@JiraKey("HHH-17102")
|
||||
public class InheritanceTests {
|
||||
|
||||
@BeforeEach
|
||||
public void prepareData(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.save( new Child( 1L, "test", 123 ) );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void cleanUpData(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
session.createQuery( "delete Child" ).executeUpdate();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResultSetMappingForParentEntity(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final List<Parent> children = session.createNamedQuery( "Parent", Parent.class ).getResultList();
|
||||
assertEquals( 1, children.size() );
|
||||
assertEquals( 1L, children.get( 0 ).id );
|
||||
assertEquals( "test", children.get( 0 ).name );
|
||||
assertInstanceOf( Child.class, children.get( 0 ) );
|
||||
assertEquals( 123, ( (Child) children.get( 0 ) ).test );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResultSetMappingForChildEntity(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
session -> {
|
||||
final List<Child> children = session.createNamedQuery( "Child", Child.class ).getResultList();
|
||||
assertEquals( 1, children.size() );
|
||||
assertEquals( 1L, children.get( 0 ).id );
|
||||
assertEquals( "test", children.get( 0 ).name );
|
||||
assertEquals( 123, children.get( 0 ).test );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@SqlResultSetMapping(
|
||||
name = "ParentResult",
|
||||
entities = {
|
||||
@EntityResult(
|
||||
entityClass = Parent.class,
|
||||
discriminatorColumn = "discr",
|
||||
fields = {
|
||||
@FieldResult(name = "id", column = "id"),
|
||||
@FieldResult(name = "name", column = "name"),
|
||||
@FieldResult(name = "test", column = "test")
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
@NamedNativeQuery(
|
||||
name = "Parent",
|
||||
query = "SELECT p.id as id, case when c.id is not null then 1 else 0 end as discr, p.name as name, c.test as test FROM parent p left join child c on p.id = c.id",
|
||||
resultSetMapping = "ParentResult"
|
||||
)
|
||||
@Entity(name = "Parent")
|
||||
@Table(name = "parent")
|
||||
@Inheritance(strategy = InheritanceType.JOINED)
|
||||
public static class Parent {
|
||||
@Id
|
||||
@Column(name = "id")
|
||||
Long id;
|
||||
String name;
|
||||
|
||||
public Parent() {
|
||||
}
|
||||
|
||||
public Parent(Long id, String name) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
@SqlResultSetMapping(
|
||||
name = "ChildResult",
|
||||
entities = {
|
||||
@EntityResult(
|
||||
entityClass = Child.class,
|
||||
fields = {
|
||||
@FieldResult(name = "id", column = "id"),
|
||||
@FieldResult(name = "name", column = "name"),
|
||||
@FieldResult(name = "test", column = "test")
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
@NamedNativeQuery(
|
||||
name = "Child",
|
||||
query = "SELECT c.id as id, 'test' as name, c.test FROM child c",
|
||||
resultSetMapping = "ChildResult"
|
||||
)
|
||||
@Entity(name = "Child")
|
||||
@Table(name = "child")
|
||||
public static class Child extends Parent {
|
||||
@Column(name = "test")
|
||||
int test;
|
||||
|
||||
public Child() {
|
||||
}
|
||||
|
||||
public Child(Long id, String name, int test) {
|
||||
super( id, name );
|
||||
this.test = test;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue