improve discriminator handling

- use fetch/result as the distinction for whether to select Class / entity-name or the "underlying type" value for discriminator.  The only time we'd have a DomainResult for the discriminator is for Query where the type is selected; all other times want the underlying type
This commit is contained in:
Steve Ebersole 2021-08-30 09:27:19 -05:00
parent aaba4767fe
commit 6f60cd8918
47 changed files with 1212 additions and 584 deletions

View File

@ -9,8 +9,9 @@ package org.hibernate.metamodel.mapping;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.FetchOptions;
@ -40,6 +41,18 @@ public interface EntityDiscriminatorMapping extends VirtualModelPart, BasicValue
String getConcreteEntityNameForDiscriminatorValue(Object value);
/**
* Create the appropriate SQL expression for this discriminator
*
* @param jdbcMappingToUse The JDBC mapping to use. This allows opting between
* the "domain result type" (aka Class) and the "underlying type" (Integer, String, etc)
*/
Expression resolveSqlExpression(
NavigablePath navigablePath,
JdbcMapping jdbcMappingToUse,
TableGroup tableGroup,
SqlAstCreationState creationState);
@Override
BasicFetch generateFetch(
FetchParent fetchParent,

View File

@ -92,6 +92,10 @@ public interface EntityMappingType extends ManagedMappingType, EntityValuedModel
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Inheritance
default boolean hasSubclasses() {
return getEntityPersister().getEntityMetamodel().hasSubclasses();
}
default AttributeMapping findDeclaredAttributeMapping(String name) {
throw new NotYetImplementedFor6Exception( getClass() );
// or ?
@ -144,16 +148,16 @@ public interface EntityMappingType extends ManagedMappingType, EntityValuedModel
EntityIdentifierMapping getIdentifierMapping();
EntityDiscriminatorMapping getDiscriminatorMapping();
Object getDiscriminatorValue();
String getSubclassForDiscriminatorValue(Object value);
EntityVersionMapping getVersionMapping();
EntityRowIdMapping getRowIdMapping();
EntityDiscriminatorMapping getDiscriminatorMapping();
EntityDiscriminatorMapping getDiscriminatorMapping(TableGroup tableGroup);
NaturalIdMapping getNaturalIdMapping();
EntityRowIdMapping getRowIdMapping();
/**
* Visit the mappings, but limited to just attributes defined
* in the targetType or its super-type(s) if any.
@ -195,6 +199,10 @@ public interface EntityMappingType extends ManagedMappingType, EntityValuedModel
return tableGroup.getPrimaryTableReference();
}
default boolean isAbstract() {
return getEntityPersister().getEntityMetamodel().isAbstract();
}
interface ConstraintOrderedTableConsumer {
void consume(String tableExpression, Supplier<Consumer<SelectableConsumer>> tableKeyColumnVisitationSupplier);
}

View File

@ -0,0 +1,397 @@
/*
* 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.metamodel.mapping.internal;
import java.util.function.BiConsumer;
import java.util.function.Function;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.metamodel.mapping.SelectableConsumer;
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.persister.entity.DiscriminatorType;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.basic.BasicFetch;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
import org.hibernate.type.spi.TypeConfiguration;
import static org.hibernate.metamodel.RepresentationMode.MAP;
/**
* @implNote `discriminatorType` represents the mapping to Class, whereas `discriminatorType.getUnderlyingType()`
* represents the "raw" JDBC mapping (String, Integer, etc)
*
* @author Steve Ebersole
*/
public abstract class AbstractDiscriminatorMapping implements EntityDiscriminatorMapping {
private final NavigableRole role;
private final JdbcMapping jdbcMapping;
private final EntityPersister entityDescriptor;
private final DiscriminatorType<?> discriminatorType;
private final SessionFactoryImplementor sessionFactory;
private final DomainResultConverter<?> domainResultConverter;
public AbstractDiscriminatorMapping(
JdbcMapping jdbcMapping,
EntityPersister entityDescriptor,
DiscriminatorType<?> discriminatorType,
MappingModelCreationProcess creationProcess) {
this.jdbcMapping = jdbcMapping;
this.entityDescriptor = entityDescriptor;
this.discriminatorType = discriminatorType;
role = entityDescriptor.getNavigableRole().append( EntityDiscriminatorMapping.ROLE_NAME );
sessionFactory = creationProcess.getCreationContext().getSessionFactory();
domainResultConverter = DomainResultConverter.create(
entityDescriptor,
this::getConcreteEntityNameForDiscriminatorValue,
discriminatorType.getUnderlyingType(),
sessionFactory
);
}
public EntityPersister getEntityDescriptor() {
return entityDescriptor;
}
public BasicType<?> getUnderlyingJdbcMappingType() {
return discriminatorType.getUnderlyingType();
}
public SessionFactoryImplementor getSessionFactory() {
return sessionFactory;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// EntityDiscriminatorMapping
@Override
public NavigableRole getNavigableRole() {
return role;
}
@Override
public JdbcMapping getJdbcMapping() {
return jdbcMapping;
}
@Override
public String getConcreteEntityNameForDiscriminatorValue(Object value) {
return getEntityDescriptor().getSubclassForDiscriminatorValue( value );
}
@Override
public EntityMappingType findContainingEntityMapping() {
return entityDescriptor;
}
@Override
public MappingType getMappedType() {
return getJdbcMapping();
}
@Override
public JavaTypeDescriptor<?> getJavaTypeDescriptor() {
return getJdbcMapping().getJavaTypeDescriptor();
}
@Override
public <T> DomainResult<T> createDomainResult(
NavigablePath navigablePath,
TableGroup tableGroup,
String resultVariable,
DomainResultCreationState creationState) {
final SqlSelection sqlSelection = resolveSqlSelection( navigablePath, getUnderlyingJdbcMappingType(), tableGroup, creationState.getSqlAstCreationState() );
//noinspection unchecked
return new BasicResult(
sqlSelection.getValuesArrayPosition(),
resultVariable,
domainResultConverter.getDomainJavaDescriptor(),
domainResultConverter,
navigablePath
);
}
private SqlSelection resolveSqlSelection(
NavigablePath navigablePath,
JdbcMapping jdbcMappingToUse,
TableGroup tableGroup,
SqlAstCreationState creationState) {
final SqlExpressionResolver expressionResolver = creationState.getSqlExpressionResolver();
return expressionResolver.resolveSqlSelection(
resolveSqlExpression( navigablePath, jdbcMappingToUse, tableGroup, creationState ),
jdbcMappingToUse.getJavaTypeDescriptor(),
creationState.getCreationContext().getDomainModel().getTypeConfiguration()
);
}
@Override
public BasicFetch generateFetch(
FetchParent fetchParent,
NavigablePath fetchablePath,
FetchTiming fetchTiming,
boolean selected,
String resultVariable,
DomainResultCreationState creationState) {
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
final TableGroup tableGroup = sqlAstCreationState.getFromClauseAccess().getTableGroup(
fetchParent.getNavigablePath()
);
assert tableGroup != null;
final SqlSelection sqlSelection = resolveSqlSelection( fetchablePath, getUnderlyingJdbcMappingType(), tableGroup, creationState.getSqlAstCreationState() );
return new BasicFetch<>(
sqlSelection.getValuesArrayPosition(),
fetchParent,
fetchablePath,
this,
false,
null,
fetchTiming,
creationState
);
}
@Override
public void applySqlSelections(
NavigablePath navigablePath,
TableGroup tableGroup,
DomainResultCreationState creationState) {
resolveSqlSelection( navigablePath, getUnderlyingJdbcMappingType(), tableGroup, creationState.getSqlAstCreationState() );
}
@Override
public void applySqlSelections(
NavigablePath navigablePath,
TableGroup tableGroup,
DomainResultCreationState creationState,
BiConsumer<SqlSelection, JdbcMapping> selectionConsumer) {
selectionConsumer.accept(
resolveSqlSelection( navigablePath, getUnderlyingJdbcMappingType(), tableGroup, creationState.getSqlAstCreationState() ),
getJdbcMapping()
);
}
@Override
public int forEachDisassembledJdbcValue(
Object value,
Clause clause,
int offset,
JdbcValuesConsumer valuesConsumer,
SharedSessionContractImplementor session) {
valuesConsumer.consume( offset, convertToRelational( value ), getJdbcMapping() );
return getJdbcTypeCount();
}
@Override
public int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) {
action.accept( offset, getJdbcMapping() );
return getJdbcTypeCount();
}
@Override
public void breakDownJdbcValues(Object domainValue, JdbcValueConsumer valueConsumer, SharedSessionContractImplementor session) {
valueConsumer.consume( convertToRelational( domainValue ), this );
}
private Object convertToRelational(Object domainValue) {
if ( domainResultConverter != null ) {
return domainResultConverter.toRelationalValue( domainValue );
}
return domainValue;
}
@Override
public Object disassemble(Object value, SharedSessionContractImplementor session) {
return convertToRelational( value );
}
@Override
public int forEachJdbcValue(Object value, Clause clause, int offset, JdbcValuesConsumer valuesConsumer, SharedSessionContractImplementor session) {
valuesConsumer.consume( offset, convertToRelational( value ), jdbcMapping );
return 1;
}
@Override
public int forEachSelectable(SelectableConsumer consumer) {
return EntityDiscriminatorMapping.super.forEachSelectable( consumer );
}
@Override
public int forEachSelectable(int offset, SelectableConsumer consumer) {
return EntityDiscriminatorMapping.super.forEachSelectable( offset, consumer );
}
@Override
public int forEachJdbcType(IndexedConsumer<JdbcMapping> action) {
return EntityDiscriminatorMapping.super.forEachJdbcType( action );
}
/**
* Used to convert the underlying discriminator value into a Class (or String for entity-name)
* reference for the entity type
*/
protected static class DomainResultConverter<R> implements BasicValueConverter<Object,R> {
/**
* Given a "raw" discriminator value, determines the corresponding concrete entity name
*/
private final Function<R,String> subtypeResolver;
/**
* Given a concrete entity name, apply the conversion to determine the "domain result" value
*
* @apiNote This is only used when building a {@link DomainResult}
*/
private final Function<String, Object> entityNameHandler;
/**
* Given a "domain form", apply the conversion to determine the corresponding relational value
*/
private final Function<Object, R> toRelationalConverter;
private final JavaTypeDescriptor<Object> domainJtd;
private final JavaTypeDescriptor<R> relationalJtd;
public DomainResultConverter(
Function<R,String> subtypeResolver,
Function<String,Object> entityNameHandler,
Function<Object,R> toRelationalConverter,
JavaTypeDescriptor<Object> domainJtd,
JavaTypeDescriptor<R> relationalJtd) {
this.subtypeResolver = subtypeResolver;
this.entityNameHandler = entityNameHandler;
this.toRelationalConverter = toRelationalConverter;
this.domainJtd = domainJtd;
this.relationalJtd = relationalJtd;
}
private static <R> DomainResultConverter<R> create(
EntityPersister entityDescriptor,
Function<R,String> subtypeResolver,
BasicType underlyingDiscriminatorType,
final SessionFactoryImplementor sessionFactory) {
final TypeConfiguration typeConfiguration = sessionFactory.getDomainModel().getTypeConfiguration();
final JavaTypeDescriptorRegistry jtdRegistry = typeConfiguration.getJavaTypeDescriptorRegistry();
final JavaTypeDescriptor<Object> domainJtd;
final Function<String,Object> entityNameHandler;
final Function<Object,Object> toRelationalConverter;
if ( entityDescriptor.getRepresentationStrategy().getMode() == MAP ) {
// todo (6.0) : account for explicit entity-name which should also return String
domainJtd = jtdRegistry.getDescriptor( String.class );
entityNameHandler = (entityName) -> entityName;
toRelationalConverter = (domainValue) -> {
if ( domainValue instanceof Class ) {
throw new IllegalArgumentException( "Illegal attempt to specify Class for discriminator for dynamic entity" );
}
if ( domainValue instanceof String ) {
final String stringValue = (String) domainValue;
// could be either an entity name or "underlying type" (e.g. mapped to VARCHAR)
// - first we check as an entity name since that's a discrete set;
// - handling as an "underlying type" value is handled in "otherwise"
if ( entityDescriptor.isSubclassEntityName( stringValue ) ) {
return entityDescriptor.getDiscriminatorValue();
}
}
// otherwise we assume its an instance of the underlying type
assert underlyingDiscriminatorType.getJavaTypeDescriptor().getJavaTypeClass().isInstance( domainJtd );
return domainJtd;
};
}
else {
final ClassLoaderService cls = sessionFactory.getServiceRegistry().getService( ClassLoaderService.class );
domainJtd = jtdRegistry.getDescriptor( Class.class );
entityNameHandler = cls::classForName;
toRelationalConverter = (domainValue) -> {
if ( domainValue instanceof Class ) {
final Class<?> classValue = (Class<?>) domainValue;
final EntityMappingType concreteEntityMapping = sessionFactory.getRuntimeMetamodels().getEntityMappingType( classValue );
return concreteEntityMapping.getDiscriminatorValue();
}
if ( domainValue instanceof String ) {
final String stringValue = (String) domainValue;
// could be either an entity name or "underlying type" (e.g. mapped to VARCHAR)
// - first we check as an entity name since that's a discrete set;
// - handling as an "underlying type" value is handled in "otherwise"
if ( entityDescriptor.isSubclassEntityName( stringValue ) ) {
return entityDescriptor.getDiscriminatorValue();
}
}
// otherwise we assume its an instance of the underlying type
assert underlyingDiscriminatorType.getJavaTypeDescriptor().getJavaTypeClass().isInstance( domainJtd );
return domainJtd;
};
}
return new DomainResultConverter(
subtypeResolver,
entityNameHandler,
toRelationalConverter,
domainJtd,
underlyingDiscriminatorType.getJavaTypeDescriptor()
);
}
@Override
public Object toDomainValue(R relationalForm) {
final String entityName = subtypeResolver.apply( relationalForm );
return entityNameHandler.apply( entityName );
}
@Override
public R toRelationalValue(Object domainForm) {
// the domainForm could be any of Class (entity type), String (entity-name) or
// underlying type (String, Integer, ..)
return toRelationalConverter.apply( domainForm );
}
@Override
public JavaTypeDescriptor<Object> getDomainJavaDescriptor() {
return domainJtd;
}
@Override
public JavaTypeDescriptor<R> getRelationalJavaDescriptor() {
return relationalJtd;
}
}
}

View File

@ -1,152 +0,0 @@
/*
* 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.metamodel.mapping.internal;
import org.hibernate.engine.FetchTiming;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.persister.entity.DiscriminatorType;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Loadable;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.basic.BasicFetch;
import org.hibernate.sql.results.graph.basic.BasicResult;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/**
* @author Andrea Boriero
*/
public abstract class AbstractEntityDiscriminatorMapping implements EntityDiscriminatorMapping {
private final EntityPersister entityDescriptor;
private final String tableExpression;
private final String mappedColumnExpression;
private final boolean isFormula;
private final DiscriminatorType<?> mappingType;
public AbstractEntityDiscriminatorMapping(
EntityPersister entityDescriptor,
String tableExpression,
String mappedColumnExpression,
boolean isFormula,
DiscriminatorType<?> mappingType) {
this.entityDescriptor = entityDescriptor;
this.tableExpression = tableExpression;
this.mappedColumnExpression = mappedColumnExpression;
this.isFormula = isFormula;
this.mappingType = mappingType;
}
public EntityPersister getEntityDescriptor() {
return entityDescriptor;
}
@Override
public String getContainingTableExpression() {
return tableExpression;
}
@Override
public String getSelectionExpression() {
return mappedColumnExpression;
}
@Override
public boolean isFormula() {
return isFormula;
}
@Override
public String getConcreteEntityNameForDiscriminatorValue(Object value) {
return ( (Loadable) getEntityDescriptor() ).getSubclassForDiscriminatorValue( value );
}
@Override
public <T> DomainResult<T> createDomainResult(
NavigablePath navigablePath,
TableGroup tableGroup,
String resultVariable,
DomainResultCreationState creationState) {
final SqlSelection sqlSelection = resolveSqlSelection( tableGroup, false, creationState );
//noinspection unchecked
return new BasicResult(
sqlSelection.getValuesArrayPosition(),
resultVariable,
getJavaTypeDescriptor(),
navigablePath
);
}
@Override
public void applySqlSelections(
NavigablePath navigablePath,
TableGroup tableGroup,
DomainResultCreationState creationState) {
resolveSqlSelection( tableGroup, false, creationState );
}
@Override
public BasicFetch generateFetch(
FetchParent fetchParent,
NavigablePath fetchablePath,
FetchTiming fetchTiming,
boolean selected,
String resultVariable,
DomainResultCreationState creationState) {
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
final TableGroup tableGroup = sqlAstCreationState.getFromClauseAccess().getTableGroup(
fetchParent.getNavigablePath()
);
assert tableGroup != null;
final SqlSelection sqlSelection = resolveSqlSelection( tableGroup, true, creationState );
return new BasicFetch<>(
sqlSelection.getValuesArrayPosition(),
fetchParent,
fetchablePath,
this,
false,
null,
fetchTiming,
creationState
);
}
@Override
public JavaTypeDescriptor<?> getJavaTypeDescriptor() {
return getMappedType().getMappedJavaTypeDescriptor();
}
@Override
public DiscriminatorType<?> getMappedType() {
return mappingType;
}
@Override
public DiscriminatorType<?> getPartMappingType() {
return mappingType;
}
@Override
public JdbcMapping getJdbcMapping() {
return mappingType.getJdbcMapping();
}
protected abstract SqlSelection resolveSqlSelection(
TableGroup tableGroup,
boolean underlyingType,
DomainResultCreationState creationState);
}

View File

@ -0,0 +1,187 @@
/*
* 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.metamodel.mapping.internal;
import java.util.LinkedHashMap;
import java.util.Map;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.persister.entity.DiscriminatorType;
import org.hibernate.persister.entity.JoinedSubclassEntityPersister;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.ast.tree.predicate.NullnessPredicate;
import org.hibernate.sql.ast.tree.predicate.Predicate;
import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey;
/**
* @author Andrea Boriero
*/
public class CaseStatementDiscriminatorMappingImpl extends AbstractDiscriminatorMapping {
private final LinkedHashMap<String,TableDiscriminatorDetails> tableDiscriminatorDetailsMap = new LinkedHashMap<>();
public CaseStatementDiscriminatorMappingImpl(
JoinedSubclassEntityPersister entityDescriptor,
String[] tableNames,
int[] notNullColumnTableNumbers,
String[] notNullColumnNames,
String[] discriminatorValues,
Map<String,String> subEntityNameByTableName,
DiscriminatorType<?> incomingDiscriminatorType,
MappingModelCreationProcess creationProcess) {
super(
incomingDiscriminatorType.getUnderlyingType().getJdbcMapping(),
entityDescriptor,
incomingDiscriminatorType,
creationProcess
);
for ( int i = 0; i < discriminatorValues.length; i++ ) {
final String tableName = tableNames[notNullColumnTableNumbers[i]];
final String subEntityName = subEntityNameByTableName.get( tableName );
final String oneSubEntityColumn = notNullColumnNames[i];
final String rawDiscriminatorValue = discriminatorValues[i];
final Object discriminatorValue = getUnderlyingJdbcMappingType().getJavaTypeDescriptor().wrap( rawDiscriminatorValue, null );
tableDiscriminatorDetailsMap.put(
tableName,
new TableDiscriminatorDetails(
tableName,
oneSubEntityColumn,
discriminatorValue,
subEntityName
)
);
}
}
@Override
public Expression resolveSqlExpression(
NavigablePath navigablePath,
JdbcMapping jdbcMappingToUse,
TableGroup tableGroup,
SqlAstCreationState creationState) {
final SqlExpressionResolver expressionResolver = creationState.getSqlExpressionResolver();
return expressionResolver.resolveSqlExpression(
createColumnReferenceKey( tableGroup.getGroupAlias(), EntityDiscriminatorMapping.ROLE_NAME ),
sqlAstProcessingState -> createCaseSearchedExpression( tableGroup )
);
}
private CaseSearchedExpression createCaseSearchedExpression(TableGroup entityTableGroup) {
final CaseSearchedExpression caseSearchedExpression = new CaseSearchedExpression( this );
tableDiscriminatorDetailsMap.forEach( (tableName, tableDiscriminatorDetails) -> {
TableReference tableReference;
try {
tableReference = entityTableGroup.resolveTableReference( entityTableGroup.getNavigablePath(), tableName );
}
catch (Exception e) {
tableReference = null;
}
if ( tableReference == null ) {
// assume this is because it is a table that is not part of the processing entity's sub-hierarchy
return;
}
final Predicate predicate = new NullnessPredicate(
new ColumnReference(
tableReference,
tableDiscriminatorDetails.getCheckColumnName(),
false,
null,
null,
getJdbcMapping(),
getSessionFactory()
),
true
);
caseSearchedExpression.when( predicate, new QueryLiteral<>(
tableDiscriminatorDetails.getDiscriminatorValue(),
getUnderlyingJdbcMappingType()
) );
} );
return caseSearchedExpression;
}
@Override
public String getCustomReadExpression() {
return null;
}
@Override
public String getCustomWriteExpression() {
return null;
}
@Override
public String getContainingTableExpression() {
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();
}
@Override
public String getSelectionExpression() {
throw new UnsupportedOperationException();
// // this *should* only be used to create the sql-expression key, so just
// // using the ROLE_NAME should be fine
// return ROLE_NAME;
}
@Override
public boolean isFormula() {
return false;
}
private static class TableDiscriminatorDetails {
private final String tableName;
private final String checkColumnName;
private final Object discriminatorValue;
private final String subclassEntityName;
public TableDiscriminatorDetails(String tableName, String checkColumnName, Object discriminatorValue, String subclassEntityName) {
this.tableName = tableName;
this.checkColumnName = checkColumnName;
this.discriminatorValue = discriminatorValue;
this.subclassEntityName = subclassEntityName;
}
String getTableExpression() {
return tableName;
}
Object getDiscriminatorValue() {
return discriminatorValue;
}
String getSubclassEntityName() {
return subclassEntityName;
}
String getCheckColumnName() {
return checkColumnName;
}
}
}

View File

@ -1,121 +0,0 @@
/*
* 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.metamodel.mapping.internal;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.persister.entity.DiscriminatorType;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.type.BasicType;
/**
* @author Steve Ebersole
*/
public class EntityDiscriminatorMappingImpl extends AbstractEntityDiscriminatorMapping {
private final NavigableRole navigableRole;
public EntityDiscriminatorMappingImpl(
EntityPersister entityDescriptor,
String tableExpression,
String mappedColumnExpression,
boolean isFormula,
DiscriminatorType<?> mappingType) {
super( entityDescriptor, tableExpression, mappedColumnExpression, isFormula, mappingType );
this.navigableRole = entityDescriptor.getNavigableRole().append( EntityDiscriminatorMapping.ROLE_NAME );
}
@Override
protected SqlSelection resolveSqlSelection(
TableGroup tableGroup,
boolean underlyingType,
DomainResultCreationState creationState) {
final SqlExpressionResolver expressionResolver = creationState.getSqlAstCreationState()
.getSqlExpressionResolver();
final TableReference tableReference = tableGroup.resolveTableReference(
tableGroup.getNavigablePath()
.append( getNavigableRole().getNavigableName() ),
getContainingTableExpression()
);
final BasicType<?> type = underlyingType ? getMappedType().getUnderlyingType() : getMappedType();
return expressionResolver.resolveSqlSelection(
expressionResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey(
tableReference,
getSelectionExpression()
),
sqlAstProcessingState -> new ColumnReference(
tableReference.getIdentificationVariable(),
this,
type,
creationState.getSqlAstCreationState().getCreationContext().getSessionFactory()
)
),
type.getMappedJavaTypeDescriptor(),
creationState.getSqlAstCreationState().getCreationContext().getDomainModel().getTypeConfiguration()
);
}
@Override
public int forEachDisassembledJdbcValue(
Object value,
Clause clause,
int offset,
JdbcValuesConsumer valuesConsumer,
SharedSessionContractImplementor session) {
valuesConsumer.consume( offset, value, getJdbcMapping() );
return getJdbcTypeCount();
}
@Override
public int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) {
action.accept( offset, getJdbcMapping() );
return getJdbcTypeCount();
}
@Override
public Object disassemble(Object value, SharedSessionContractImplementor session) {
return value;
}
@Override
public NavigableRole getNavigableRole() {
return navigableRole;
}
@Override
public void breakDownJdbcValues(Object domainValue, JdbcValueConsumer valueConsumer, SharedSessionContractImplementor session) {
valueConsumer.consume( domainValue, this );
}
@Override
public EntityMappingType findContainingEntityMapping() {
return getEntityDescriptor();
}
@Override
public String getCustomReadExpression() {
return null;
}
@Override
public String getCustomWriteExpression() {
return null;
}
}

View File

@ -0,0 +1,99 @@
/*
* 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.metamodel.mapping.internal;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.persister.entity.DiscriminatorType;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.query.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 static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey;
/**
* @author Steve Ebersole
*/
public class ExplicitColumnDiscriminatorMappingImpl extends AbstractDiscriminatorMapping {
private final String tableExpression;
private final String columnName;
private final String columnFormula;
public ExplicitColumnDiscriminatorMappingImpl(
EntityPersister entityDescriptor,
DiscriminatorType<?> discriminatorType,
String tableExpression,
String columnExpression,
boolean isFormula,
MappingModelCreationProcess creationProcess) {
super( discriminatorType.getJdbcMapping(), entityDescriptor, discriminatorType, creationProcess );
this.tableExpression = tableExpression;
if ( isFormula ) {
columnName = null;
columnFormula = columnExpression;
}
else {
columnName = columnExpression;
columnFormula = null;
}
}
@Override
public Expression resolveSqlExpression(
NavigablePath navigablePath,
JdbcMapping jdbcMappingToUse,
TableGroup tableGroup,
SqlAstCreationState creationState) {
final SqlExpressionResolver expressionResolver = creationState.getSqlExpressionResolver();
final TableReference tableReference = tableGroup.resolveTableReference( navigablePath, tableExpression );
return expressionResolver.resolveSqlExpression(
createColumnReferenceKey( tableReference, EntityDiscriminatorMapping.ROLE_NAME ),
sqlAstProcessingState -> new ColumnReference(
tableReference,
columnFormula == null ? columnName : columnFormula,
columnFormula != null,
null,
null,
jdbcMappingToUse,
getSessionFactory()
)
);
}
@Override
public String getContainingTableExpression() {
return tableExpression;
}
@Override
public String getSelectionExpression() {
return columnName == null ? columnFormula : columnName;
}
@Override
public String getCustomReadExpression() {
return null;
}
@Override
public String getCustomWriteExpression() {
return null;
}
@Override
public boolean isFormula() {
return columnFormula != null;
}
}

View File

@ -1,104 +0,0 @@
/*
* 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.metamodel.mapping.internal;
import java.util.List;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.mapping.IndexedConsumer;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.persister.entity.DiscriminatorType;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.CaseSearchedExpression;
import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.type.BasicType;
/**
* @author Andrea Boriero
*/
public class JoinedSubclassDiscriminatorMappingImpl extends AbstractEntityDiscriminatorMapping {
private final NavigableRole navigableRole;
private final CaseSearchedExpression caseSearchedExpression;
private final CaseSearchedExpression caseSearchedExpressionUnderlying;
public JoinedSubclassDiscriminatorMappingImpl(
EntityPersister entityDescriptor,
String tableExpression,
String mappedColumnExpression,
boolean isFormula,
CaseSearchedExpression caseSearchedExpression,
List<ColumnReference> columnReferences,
DiscriminatorType<?> mappingType) {
super( entityDescriptor, tableExpression, mappedColumnExpression, isFormula, mappingType );
this.navigableRole = entityDescriptor.getNavigableRole().append( EntityDiscriminatorMapping.ROLE_NAME );
this.caseSearchedExpression = caseSearchedExpression;
final CaseSearchedExpression caseSearchedExpressionUnderlying = new CaseSearchedExpression( mappingType.getUnderlyingType() );
for ( CaseSearchedExpression.WhenFragment whenFragment : caseSearchedExpression.getWhenFragments() ) {
caseSearchedExpressionUnderlying.when( whenFragment.getPredicate(), whenFragment.getResult() );
}
caseSearchedExpressionUnderlying.otherwise( caseSearchedExpression.getOtherwise() );
this.caseSearchedExpressionUnderlying = caseSearchedExpressionUnderlying;
}
@Override
protected SqlSelection resolveSqlSelection(
TableGroup tableGroup,
boolean underlyingType,
DomainResultCreationState creationState) {
final SqlExpressionResolver expressionResolver = creationState.getSqlAstCreationState()
.getSqlExpressionResolver();
final BasicType<?> type = underlyingType ? getMappedType().getUnderlyingType() : getMappedType();
return expressionResolver.resolveSqlSelection(
expressionResolver.resolveSqlExpression(
getSelectionExpression(),
sqlAstProcessingState -> underlyingType ? caseSearchedExpressionUnderlying : caseSearchedExpression
),
type.getMappedJavaTypeDescriptor(),
creationState.getSqlAstCreationState().getCreationContext().getDomainModel().getTypeConfiguration()
);
}
@Override
public NavigableRole getNavigableRole() {
return navigableRole;
}
@Override
public void breakDownJdbcValues(Object domainValue, JdbcValueConsumer valueConsumer, SharedSessionContractImplementor session) {
valueConsumer.consume( domainValue, this );
}
@Override
public EntityMappingType findContainingEntityMapping() {
return getEntityDescriptor();
}
@Override
public String getCustomReadExpression() {
return null;
}
@Override
public String getCustomWriteExpression() {
return null;
}
@Override
public int forEachJdbcType(int offset, IndexedConsumer<JdbcMapping> action) {
action.accept( offset, getJdbcMapping() );
return getJdbcTypeCount();
}
}

View File

@ -0,0 +1,92 @@
/*
* 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.metamodel.model.domain.internal;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.PathException;
import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.IllegalPathUsageException;
import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.sql.internal.DiscriminatorPathInterpretation;
import org.hibernate.query.sqm.sql.internal.SelfInterpretingSqmPath;
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
import org.hibernate.query.sqm.tree.domain.AbstractSqmPath;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
import org.hibernate.query.sqm.tree.expression.SqmLiteralEntityType;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.tree.from.TableGroup;
/**
* SqmPath specialization for an entity discriminator
*
* @author Steve Ebersole
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public class DiscriminatorSqmPath extends AbstractSqmPath implements SelfInterpretingSqmPath {
private final EntityDomainType entityDomainType;
private final EntityMappingType entityDescriptor;
protected DiscriminatorSqmPath(
SqmPathSource referencedPathSource,
SqmPath<?> lhs,
EntityDomainType entityDomainType,
EntityMappingType entityDescriptor,
NodeBuilder nodeBuilder) {
super( lhs.getNavigablePath().append( EntityDiscriminatorMapping.ROLE_NAME ), referencedPathSource, lhs, nodeBuilder );
this.entityDomainType = entityDomainType;
this.entityDescriptor = entityDescriptor;
}
@Override
public <X> X accept(SemanticQueryWalker<X> walker) {
if ( ! entityDescriptor.hasSubclasses() ) {
return walker.visitEntityTypeLiteralExpression( new SqmLiteralEntityType( entityDomainType, nodeBuilder() ) );
}
return walker.visitSelfInterpretingSqmPath( this );
}
@Override
public SqmPathInterpretation<?> interpret(
SqlAstCreationState sqlAstCreationState,
SemanticQueryWalker sqmWalker,
boolean jpaQueryComplianceEnabled) {
assert entityDescriptor.hasSubclasses();
final TableGroup tableGroup = sqlAstCreationState.getFromClauseAccess().getTableGroup( getLhs().getNavigablePath() );
final EntityMappingType entityMapping = ( (EntityValuedModelPart) tableGroup.getModelPart() ).getEntityMappingType();
return new DiscriminatorPathInterpretation( getNavigablePath(), entityMapping, tableGroup, sqlAstCreationState );
}
@Override
public void appendHqlString(StringBuilder sb) {
// todo (6.0) : no idea
}
@Override
public SemanticPathPart resolvePathPart(String name, boolean isTerminal, SqmCreationState creationState) {
throw new IllegalPathUsageException( "Discriminator cannot be de-referenced" );
}
@Override
public SqmTreatedPath treatAs(Class treatJavaType) throws PathException {
throw new UnsupportedOperationException( "Cannot apply TREAT operator to discriminator path" );
}
@Override
public SqmTreatedPath treatAs(EntityDomainType treatTarget) throws PathException {
throw new UnsupportedOperationException( "Cannot apply TREAT operator to discriminator path" );
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.metamodel.model.domain.internal;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.sqm.IllegalPathUsageException;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.tree.domain.SqmPath;
/**
* SqmPathSource implementation for entity discriminator
*
* @author Steve Ebersole
*/
public class DiscriminatorSqmPathSource<D> extends AbstractSqmPathSource<D> {
private final EntityDomainType<?> entityDomainType;
private final EntityMappingType entityMapping;
public DiscriminatorSqmPathSource(
DomainType<D> discriminatorValueType,
EntityDomainType<?> entityDomainType,
EntityMappingType entityMapping) {
super( EntityDiscriminatorMapping.ROLE_NAME, discriminatorValueType, BindableType.SINGULAR_ATTRIBUTE );
this.entityDomainType = entityDomainType;
this.entityMapping = entityMapping;
}
@Override
public SqmPath<D> createSqmPath(SqmPath<?> lhs) {
return new DiscriminatorSqmPath( this, lhs, entityDomainType, entityMapping, lhs.nodeBuilder() );
}
@Override
public SqmPathSource<?> findSubPathSource(String name) throws IllegalPathUsageException {
throw new IllegalPathUsageException( "Entity discriminator cannot be de-referenced" );
}
}

View File

@ -22,10 +22,7 @@ import org.hibernate.metamodel.model.domain.PersistentAttribute;
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
import org.hibernate.persister.entity.DiscriminatorMetadata;
import org.hibernate.persister.entity.Queryable;
import org.hibernate.query.sqm.IllegalPathUsageException;
import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedEntityTypePath;
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
@ -71,59 +68,12 @@ public class EntityTypeImpl<J>
else {
discriminatorType = StandardBasicTypes.STRING;
}
final boolean hasSubclasses = persistentClass.hasSubclasses();
this.discriminatorPathSource = new SqmPathSource() {
@Override
public String getPathName() {
return EntityDiscriminatorMapping.ROLE_NAME;
}
@Override
public DomainType<?> getSqmPathType() {
// the BasicType for Class?
return discriminatorType;
}
@Override
public SqmPathSource<?> findSubPathSource(String name) {
throw new IllegalPathUsageException( "Entity discriminator cannot be de-referenced" );
}
@Override
public SqmPath<?> createSqmPath(SqmPath lhs) {
if ( hasSubclasses ) {
return new SqmBasicValuedSimplePath<>(
lhs.getNavigablePath().append( EntityDiscriminatorMapping.ROLE_NAME ),
this,
lhs,
lhs.nodeBuilder()
);
}
else {
return new SqmBasicValuedEntityTypePath<>(
lhs.getNavigablePath().append( EntityDiscriminatorMapping.ROLE_NAME ),
EntityTypeImpl.this,
lhs,
lhs.nodeBuilder()
);
}
}
@Override
public BindableType getBindableType() {
return BindableType.SINGULAR_ATTRIBUTE;
}
@Override
public Class<?> getBindableJavaType() {
return getExpressableJavaTypeDescriptor().getJavaTypeClass();
}
@Override
public JavaTypeDescriptor<?> getExpressableJavaTypeDescriptor() {
return discriminatorType.getExpressableJavaTypeDescriptor();
}
};
this.discriminatorPathSource = new DiscriminatorSqmPathSource<>(
discriminatorType,
this,
entityPersister
);
}
@Override

View File

@ -107,7 +107,6 @@ import org.hibernate.id.insert.InsertGeneratedIdentifierDelegate;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.FilterHelper;
import org.hibernate.internal.util.MutableBoolean;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
@ -167,9 +166,9 @@ import org.hibernate.metamodel.mapping.internal.BasicEntityIdentifierMappingImpl
import org.hibernate.metamodel.mapping.internal.CompoundNaturalIdMapping;
import org.hibernate.metamodel.mapping.internal.DiscriminatedAssociationAttributeMapping;
import org.hibernate.metamodel.mapping.internal.EmbeddedAttributeMapping;
import org.hibernate.metamodel.mapping.internal.EntityDiscriminatorMappingImpl;
import org.hibernate.metamodel.mapping.internal.EntityRowIdMappingImpl;
import org.hibernate.metamodel.mapping.internal.EntityVersionMappingImpl;
import org.hibernate.metamodel.mapping.internal.ExplicitColumnDiscriminatorMappingImpl;
import org.hibernate.metamodel.mapping.internal.GeneratedValuesProcessor;
import org.hibernate.metamodel.mapping.internal.InFlightEntityMappingType;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper;
@ -208,7 +207,6 @@ import org.hibernate.sql.Update;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
import org.hibernate.sql.ast.spi.SqlAliasStemHelper;
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
@ -6033,7 +6031,7 @@ public abstract class AbstractEntityPersister
);
}
discriminatorMapping = generateDiscriminatorMapping();
discriminatorMapping = generateDiscriminatorMapping( creationProcess );
}
private void postProcessAttributeMappings(MappingModelCreationProcess creationProcess, PersistentClass bootEntityDescriptor) {
@ -6146,7 +6144,7 @@ public abstract class AbstractEntityPersister
return stateArrayPosition;
}
protected EntityDiscriminatorMapping generateDiscriminatorMapping() {
protected EntityDiscriminatorMapping generateDiscriminatorMapping(MappingModelCreationProcess modelCreationProcess) {
if ( getDiscriminatorType() == null) {
return null;
}
@ -6158,12 +6156,13 @@ public abstract class AbstractEntityPersister
else {
discriminatorColumnExpression = getDiscriminatorFormulaTemplate();
}
return new EntityDiscriminatorMappingImpl(
return new ExplicitColumnDiscriminatorMappingImpl (
this,
(DiscriminatorType<?>) getTypeDiscriminatorMetadata().getResolutionType(),
getTableName(),
discriminatorColumnExpression,
getDiscriminatorFormulaTemplate() != null,
(DiscriminatorType<?>) getTypeDiscriminatorMetadata().getResolutionType()
modelCreationProcess
);
}
}
@ -6591,11 +6590,6 @@ public abstract class AbstractEntityPersister
return discriminatorMapping;
}
@Override
public EntityDiscriminatorMapping getDiscriminatorMapping(TableGroup tableGroup) {
return discriminatorMapping;
}
@Override
public List<AttributeMapping> getAttributeMappings() {
if ( attributeMappings == null ) {

View File

@ -22,6 +22,7 @@ import org.hibernate.engine.spi.Mapping;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.type.AbstractType;
import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.ValueBinder;
@ -50,6 +51,11 @@ public class DiscriminatorType<T> extends AbstractType implements org.hibernate.
return underlyingType;
}
@Override
public JdbcMapping getJdbcMapping() {
return getUnderlyingType().getJdbcMapping();
}
@Override
public Class getReturnedClass() {
return Class.class;

View File

@ -48,7 +48,7 @@ import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityVersionMapping;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.internal.BasicEntityIdentifierMappingImpl;
import org.hibernate.metamodel.mapping.internal.JoinedSubclassDiscriminatorMappingImpl;
import org.hibernate.metamodel.mapping.internal.CaseStatementDiscriminatorMappingImpl;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationHelper;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.persister.spi.PersisterCreationContext;
@ -130,7 +130,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
private final boolean[] isNullableSubclassTable;
// subclass discrimination works by assigning particular
// values to certain combinations of null primary key
// values to certain combinations of not-null primary key
// values in the outer join using an SQL CASE
private final Map<Object,String> subclassesByDiscriminatorValue = new HashMap<>();
private final String[] discriminatorValues;
@ -580,7 +580,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
Subclass sc = siter.next();
subclassClosure[k] = sc.getEntityName();
final Table table = sc.getTable();
subclassNameByTableName.put( table.getName(), sc.getClassName() );
subclassNameByTableName.put( table.getName(), sc.getEntityName() );
try {
if ( persistentClass.isPolymorphic() ) {
final Object discriminatorValue;
@ -1218,17 +1218,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
return null;
}
@Override
protected EntityDiscriminatorMapping generateDiscriminatorMapping() {
EntityMappingType superMappingType = getSuperMappingType();
if ( superMappingType != null ) {
return superMappingType.getDiscriminatorMapping();
}
else {
return super.generateDiscriminatorMapping();
}
}
@Override
protected EntityIdentifierMapping generateIdentifierMapping(MappingModelCreationProcess creationProcess, PersistentClass bootEntityDescriptor) {
final Type idType = getIdentifierType();
@ -1268,6 +1257,40 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
);
}
@Override
protected EntityDiscriminatorMapping generateDiscriminatorMapping(MappingModelCreationProcess modelCreationProcess) {
EntityMappingType superMappingType = getSuperMappingType();
if ( superMappingType != null ) {
return superMappingType.getDiscriminatorMapping();
}
if ( hasSubclasses() ) {
final String formula = getDiscriminatorFormulaTemplate();
if ( explicitDiscriminatorColumnName != null || formula != null ) {
// even though this is a joined-hierarchy the user has defined an
// explicit discriminator column - so we can use the normal
// discriminator mapping
return super.generateDiscriminatorMapping( modelCreationProcess );
}
org.hibernate.persister.entity.DiscriminatorType<?> discriminatorMetadataType = (org.hibernate.persister.entity.DiscriminatorType<?>) getTypeDiscriminatorMetadata().getResolutionType();
// otherwise, we need to use the case-statement approach
return new CaseStatementDiscriminatorMappingImpl(
this,
subclassTableNameClosure,
notNullColumnTableNumbers,
notNullColumnNames,
discriminatorValues,
subclassNameByTableName,
discriminatorMetadataType,
modelCreationProcess
);
}
return null;
}
protected EntityIdentifierMapping generateNonEncapsulatedCompositeIdentifierMapping(
MappingModelCreationProcess creationProcess,
PersistentClass bootEntityDescriptor,
@ -1310,35 +1333,6 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
}
}
@Override
public EntityDiscriminatorMapping getDiscriminatorMapping(TableGroup tableGroup) {
if ( hasSubclasses() ) {
if ( explicitDiscriminatorColumnName == null ) {
final String discriminatorColumnExpression;
if ( getDiscriminatorFormulaTemplate() == null ) {
discriminatorColumnExpression = getDiscriminatorColumnName();
}
else {
discriminatorColumnExpression = getDiscriminatorFormulaTemplate();
}
CaseSearchedExpressionInfo info = getCaseSearchedExpression( tableGroup );
return new JoinedSubclassDiscriminatorMappingImpl(
this,
getTableName(),
discriminatorColumnExpression,
getDiscriminatorFormulaTemplate() != null,
info.caseSearchedExpression,
info.columnReferences,
(org.hibernate.persister.entity.DiscriminatorType<?>) getTypeDiscriminatorMetadata().getResolutionType()
);
}
else {
return super.getDiscriminatorMapping( tableGroup );
}
}
return null;
}
@Override
public void visitConstraintOrderedTables(ConstraintOrderedTableConsumer consumer) {
for ( int i = 0; i < constraintOrderedTableNames.length; i++ ) {

View File

@ -42,6 +42,7 @@ import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Subclass;
import org.hibernate.mapping.Table;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.internal.MappingModelCreationProcess;
import org.hibernate.persister.spi.PersisterCreationContext;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.SelectFragment;
@ -405,9 +406,9 @@ public class UnionSubclassEntityPersister extends AbstractEntityPersister {
}
@Override
protected EntityDiscriminatorMapping generateDiscriminatorMapping() {
protected EntityDiscriminatorMapping generateDiscriminatorMapping(MappingModelCreationProcess modelCreationProcess) {
if ( hasSubclasses() ) {
return super.generateDiscriminatorMapping();
return super.generateDiscriminatorMapping( modelCreationProcess );
}
return null;
}

View File

@ -9,6 +9,8 @@ package org.hibernate.query.sqm;
import java.util.List;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.metamodel.model.domain.internal.DiscriminatorSqmPath;
import org.hibernate.query.sqm.sql.internal.SelfInterpretingSqmPath;
import org.hibernate.query.sqm.tree.cte.SqmCteContainer;
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
@ -144,6 +146,8 @@ public interface SemanticQueryWalker<T> {
T visitEntityValuedPath(SqmEntityValuedSimplePath<?> path);
T visitPluralValuedPath(SqmPluralValuedSimplePath<?> path);
T visitSelfInterpretingSqmPath(SelfInterpretingSqmPath sqmPath);
T visitIndexedPluralAccessPath(SqmIndexedCollectionAccessPath path);

View File

@ -12,6 +12,7 @@ import java.util.Locale;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.query.QueryLogging;
import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.sql.internal.SelfInterpretingSqmPath;
import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.query.sqm.tree.cte.SqmCteContainer;
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
@ -584,6 +585,13 @@ public class SqmTreePrinter implements SemanticQueryWalker<Object> {
return null;
}
@Override
public Object visitSelfInterpretingSqmPath(SelfInterpretingSqmPath sqmPath) {
logWithIndentation( "-> [self-interpreting-path] - `%s`", sqmPath.getNavigablePath().getFullPath() );
return null;
}
@Override
public Object visitEntityValuedPath(SqmEntityValuedSimplePath path) {
logWithIndentation( "-> [entity-path] - `%s`", path.getNavigablePath().getFullPath() );

View File

@ -10,6 +10,7 @@ import java.util.List;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.sql.internal.SelfInterpretingSqmPath;
import org.hibernate.query.sqm.tree.SqmStatement;
import org.hibernate.query.sqm.tree.cte.SqmCteContainer;
import org.hibernate.query.sqm.tree.cte.SqmCteStatement;
@ -287,6 +288,11 @@ public abstract class BaseSemanticQueryWalker implements SemanticQueryWalker<Obj
return path;
}
@Override
public Object visitSelfInterpretingSqmPath(SelfInterpretingSqmPath sqmPath) {
return sqmPath;
}
@Override
public Object visitIndexedPluralAccessPath(SqmIndexedCollectionAccessPath path) {
return path;

View File

@ -72,6 +72,7 @@ import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
import org.hibernate.metamodel.model.domain.internal.CompositeSqmPathSource;
import org.hibernate.metamodel.model.domain.internal.DiscriminatorSqmPath;
import org.hibernate.param.VersionTypeSeedParameterSpecification;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
@ -104,6 +105,7 @@ import org.hibernate.query.sqm.sql.internal.EmbeddableValuedPathInterpretation;
import org.hibernate.query.sqm.sql.internal.EntityValuedPathInterpretation;
import org.hibernate.query.sqm.sql.internal.NonAggregatedCompositeValuedPathInterpretation;
import org.hibernate.query.sqm.sql.internal.PluralValuedSimplePathInterpretation;
import org.hibernate.query.sqm.sql.internal.SelfInterpretingSqmPath;
import org.hibernate.query.sqm.sql.internal.SqlAstProcessingStateImpl;
import org.hibernate.query.sqm.sql.internal.SqlAstQueryPartProcessingStateImpl;
import org.hibernate.query.sqm.sql.internal.SqmMapEntryResult;
@ -2381,6 +2383,11 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
return PluralValuedSimplePathInterpretation.from( sqmPath, this );
}
@Override
public Object visitSelfInterpretingSqmPath(SelfInterpretingSqmPath sqmPath) {
return sqmPath.interpret( this, this, jpaQueryComplianceEnabled );
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// General expressions

View File

@ -0,0 +1,70 @@
/*
* 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.query.sqm.sql.internal;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlSelection;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.spi.TypeConfiguration;
/**
* SqmPathInterpretation and DomainResultProducer implementation for entity discriminator
*
* @author Steve Ebersole
*/
public class DiscriminatorPathInterpretation extends AbstractSqmPathInterpretation implements DomainResultProducer {
private final Expression expression;
public DiscriminatorPathInterpretation(
NavigablePath navigablePath,
EntityMappingType mapping,
TableGroup tableGroup,
SqlAstCreationState sqlAstCreationState) {
super( navigablePath, mapping.getDiscriminatorMapping(), tableGroup );
final JdbcMapping jdbcMappingToUse = mapping.getDiscriminatorMapping().getJdbcMapping();
expression = getDiscriminatorMapping().resolveSqlExpression( navigablePath, jdbcMappingToUse, tableGroup, sqlAstCreationState );
}
public EntityDiscriminatorMapping getDiscriminatorMapping() {
return (EntityDiscriminatorMapping) super.getExpressionType();
}
@Override
public EntityDiscriminatorMapping getExpressionType() {
return getDiscriminatorMapping();
}
@Override
public SqlSelection createSqlSelection(
int jdbcPosition,
int valuesArrayPosition,
JavaTypeDescriptor javaTypeDescriptor,
TypeConfiguration typeConfiguration) {
return new SqlSelectionImpl( valuesArrayPosition, getDiscriminatorMapping() );
}
@Override
public DomainResult<Class<?>> createDomainResult(String resultVariable, DomainResultCreationState creationState) {
return getDiscriminatorMapping().createDomainResult( getNavigablePath(), getTableGroup(), resultVariable, creationState );
}
@Override
public void accept(SqlAstWalker sqlTreeWalker) {
expression.accept( sqlTreeWalker );
}
}

View File

@ -0,0 +1,26 @@
/*
* 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.query.sqm.sql.internal;
import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.sql.ast.spi.SqlAstCreationState;
/**
* Optional contract for sqm-paths which need special interpretation handling
*
* @author Steve Ebersole
*/
public interface SelfInterpretingSqmPath<T> extends SqmPath<T> {
/**
* Perform the interpretation
*/
SqmPathInterpretation<T> interpret(
SqlAstCreationState sqlAstCreationState,
SemanticQueryWalker<?> sqmWalker,
boolean jpaQueryComplianceEnabled);
}

View File

@ -39,24 +39,12 @@ public abstract class AbstractEntityResultGraphNode extends AbstractFetchParent
private final BasicFetch<?> discriminatorFetch;
private final DomainResult<Object> rowIdResult;
private final EntityMappingType targetType;
public AbstractEntityResultGraphNode(
EntityValuedModelPart referencedModelPart,
NavigablePath navigablePath,
DomainResultCreationState creationState) {
this( referencedModelPart, navigablePath, null, creationState );
}
@SuppressWarnings("WeakerAccess")
public AbstractEntityResultGraphNode(
EntityValuedModelPart referencedModelPart,
NavigablePath navigablePath,
EntityMappingType targetType,
DomainResultCreationState creationState) {
super( referencedModelPart.getEntityMappingType(), navigablePath );
this.referencedModelPart = referencedModelPart;
this.targetType = targetType;
final EntityMappingType entityDescriptor = referencedModelPart.getEntityMappingType();
@ -100,9 +88,9 @@ public abstract class AbstractEntityResultGraphNode extends AbstractFetchParent
);
}
final EntityDiscriminatorMapping discriminatorMapping = getDiscriminatorMapping( entityDescriptor, entityTableGroup );
final EntityDiscriminatorMapping discriminatorMapping = entityDescriptor.getDiscriminatorMapping();
// No need to fetch the discriminator if this type does not have subclasses
if ( discriminatorMapping != null && entityDescriptor.getEntityPersister().getEntityMetamodel().hasSubclasses() ) {
if ( discriminatorMapping != null && entityDescriptor.hasSubclasses() ) {
discriminatorFetch = discriminatorMapping.generateFetch(
this,
navigablePath.append( EntityDiscriminatorMapping.ROLE_NAME ),
@ -168,12 +156,6 @@ public abstract class AbstractEntityResultGraphNode extends AbstractFetchParent
}
}
protected EntityDiscriminatorMapping getDiscriminatorMapping(
EntityMappingType entityDescriptor,
TableGroup entityTableGroup) {
return entityDescriptor.getDiscriminatorMapping( entityTableGroup );
}
@Override
public EntityMappingType getReferencedMappingContainer() {
return getEntityValuedModelPart().getEntityMappingType();

View File

@ -6,10 +6,7 @@
*/
package org.hibernate.sql.results.graph.entity.internal;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.persister.entity.JoinedSubclassEntityPersister;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.AssemblerCreationState;
@ -49,16 +46,4 @@ public class EntityResultJoinedSubclassImpl extends EntityResultImpl {
return new EntityAssembler( getResultJavaTypeDescriptor(), initializer );
}
@Override
protected EntityDiscriminatorMapping getDiscriminatorMapping(
EntityMappingType entityDescriptor,
TableGroup entityTableGroup) {
final JoinedSubclassEntityPersister joinedSubclassEntityPersister = (JoinedSubclassEntityPersister) entityDescriptor;
if ( joinedSubclassEntityPersister.hasSubclasses() ) {
return joinedSubclassEntityPersister.getDiscriminatorMapping( entityTableGroup );
}
else {
return null;
}
}
}

View File

@ -12,6 +12,7 @@ import java.sql.SQLException;
import javax.persistence.AttributeConverter;
import javax.persistence.PersistenceException;
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
@ -24,11 +25,11 @@ public class ConvertedValueExtractor<O,R> implements ValueExtractor<O> {
private static final Logger log = Logger.getLogger( ConvertedValueExtractor.class );
private final ValueExtractor<R> relationalExtractor;
private final AttributeConverter<O,R> converter;
private final BasicValueConverter<O,R> converter;
public ConvertedValueExtractor(
ValueExtractor<R> relationalExtractor,
AttributeConverter<O, R> converter) {
BasicValueConverter<O, R> converter) {
this.relationalExtractor = relationalExtractor;
this.converter = converter;
}
@ -50,7 +51,7 @@ public class ConvertedValueExtractor<O,R> implements ValueExtractor<O> {
private O doConversion(R extractedValue) {
try {
O convertedValue = converter.convertToEntityAttribute( extractedValue );
O convertedValue = converter.toDomainValue( extractedValue );
log.debugf( "Converted value on extraction: %s -> %s", extractedValue, convertedValue );
return convertedValue;
}

View File

@ -643,7 +643,12 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver {
}
@Override
public EntityDiscriminatorMapping getDiscriminatorMapping(TableGroup tableGroup) {
public Object getDiscriminatorValue() {
return null;
}
@Override
public String getSubclassForDiscriminatorValue(Object value) {
return null;
}

View File

@ -696,7 +696,12 @@ public class PersisterClassProviderTest {
}
@Override
public EntityDiscriminatorMapping getDiscriminatorMapping(TableGroup tableGroup) {
public Object getDiscriminatorValue() {
return null;
}
@Override
public String getSubclassForDiscriminatorValue(Object value) {
return null;
}

View File

@ -754,7 +754,12 @@ public class CustomPersister implements EntityPersister {
}
@Override
public EntityDiscriminatorMapping getDiscriminatorMapping(TableGroup tableGroup) {
public Object getDiscriminatorValue() {
return null;
}
@Override
public String getSubclassForDiscriminatorValue(Object value) {
return null;
}

View File

@ -6,7 +6,7 @@
*/
//$Id: Address.java 4373 2004-08-18 09:18:34Z oneovthafew $
package org.hibernate.orm.test.discriminator;
package org.hibernate.orm.test.mapping.inheritance.discriminator;
/**

View File

@ -6,7 +6,7 @@
*/
//$Id: Customer.java 4373 2004-08-18 09:18:34Z oneovthafew $
package org.hibernate.orm.test.discriminator;
package org.hibernate.orm.test.mapping.inheritance.discriminator;
/**

View File

@ -4,7 +4,7 @@
* 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.discriminator;
package org.hibernate.orm.test.mapping.inheritance.discriminator;
import javax.persistence.Tuple;
@ -21,7 +21,7 @@ import org.assertj.core.api.Assertions;
* @author Steve Ebersole
*/
@DomainModel(
xmlMappings = "org/hibernate/orm/test/discriminator/Person.hbm.xml"
xmlMappings = "org/hibernate/orm/test/mapping/inheritance/discriminator/Person.hbm.xml"
)
@SessionFactory
public class DiscriminatorQueryUsageTests {

View File

@ -1,10 +1,10 @@
/*
* 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>.
* 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.discriminator;
package org.hibernate.orm.test.mapping.inheritance.discriminator;
import java.math.BigDecimal;
import java.util.List;
@ -37,7 +37,7 @@ import static org.junit.jupiter.api.Assertions.fail;
* @author Gavin King
*/
@DomainModel(
xmlMappings = "org/hibernate/orm/test/discriminator/Person.hbm.xml"
xmlMappings = "org/hibernate/orm/test/mapping/inheritance/discriminator/Person.hbm.xml"
)
@SessionFactory
public class DiscriminatorTest {

View File

@ -6,7 +6,7 @@
*/
//$Id: Employee.java 4373 2004-08-18 09:18:34Z oneovthafew $
package org.hibernate.orm.test.discriminator;
package org.hibernate.orm.test.mapping.inheritance.discriminator;
import java.math.BigDecimal;
/**

View File

@ -6,7 +6,7 @@
*/
//$Id: Employee.java 4373 2004-08-18 09:18:34Z oneovthafew $
package org.hibernate.orm.test.discriminator;
package org.hibernate.orm.test.mapping.inheritance.discriminator;
import java.math.BigDecimal;
/**

View File

@ -18,7 +18,7 @@
-->
<hibernate-mapping
package="org.hibernate.orm.test.discriminator"
package="org.hibernate.orm.test.mapping.inheritance.discriminator"
default-access="field">
<class name="Person"

View File

@ -6,7 +6,7 @@
*/
//$Id: Person.java 4373 2004-08-18 09:18:34Z oneovthafew $
package org.hibernate.orm.test.discriminator;
package org.hibernate.orm.test.mapping.inheritance.discriminator;

View File

@ -11,7 +11,7 @@
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="org.hibernate.orm.test.discriminator"
package="org.hibernate.orm.test.mapping.inheritance.discriminator"
default-access="field">
<!--

View File

@ -1,10 +1,10 @@
/*
* 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>.
* 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.discriminator;
package org.hibernate.orm.test.mapping.inheritance.discriminator;
import java.math.BigDecimal;
import java.util.List;
@ -34,7 +34,10 @@ import static org.junit.jupiter.api.Assertions.fail;
* @author Gavin King
*/
@DomainModel(
xmlMappings = "org/hibernate/orm/test/discriminator/SimpleInheritance.hbm.xml"
xmlMappings = {
"org/hibernate/orm/test/mapping/inheritance/discriminator/SimpleInheritance.hbm.xml",
"org/hibernate/orm/test/mapping/inheritance/discriminator/Person.hbm.xml"
}
)
@SessionFactory
public class SimpleInheritanceTest {
@ -81,28 +84,28 @@ public class SimpleInheritanceTest {
}
assertThat(
s.createQuery( "from org.hibernate.orm.test.discriminator.Person" ).list().size(),
s.createQuery( "from Person" ).list().size(),
is( 3 )
);
assertThat( s.createQuery(
"from org.hibernate.orm.test.discriminator.Person p where p.class = org.hibernate.orm.test.discriminator.Person" )
"from Person p where p.class = Person" )
.list()
.size(), is( 1 ) );
assertThat( s.createQuery(
"from org.hibernate.orm.test.discriminator.Person p where p.class = org.hibernate.orm.test.discriminator.Customer" )
"from Person p where p.class = Customer" )
.list()
.size(), is( 1 ) );
assertThat( s.createQuery( "from org.hibernate.orm.test.discriminator.Person p where type(p) = :who" )
assertThat( s.createQuery( "from Person p where type(p) = :who" )
.setParameter( "who", Person.class )
.list()
.size(), is( 1 ) );
assertThat( s.createQuery( "from org.hibernate.orm.test.discriminator.Person p where type(p) in :who" )
assertThat( s.createQuery( "from Person p where type(p) in :who" )
.setParameterList( "who", new Class[] { Customer.class, Person.class } )
.list()
.size(), is( 2 ) );
s.clear();
List<Customer> customers = s.createQuery( "from org.hibernate.orm.test.discriminator.Customer" ).list();
List<Customer> customers = s.createQuery( "from Customer" ).list();
for ( Customer c : customers ) {
assertThat( c.getComments(), is( "Very demanding" ) );
}
@ -115,7 +118,7 @@ public class SimpleInheritanceTest {
s.delete( mark );
s.delete( joe );
s.delete( yomomma );
assertTrue( s.createQuery( "from org.hibernate.orm.test.discriminator.Person" ).list().isEmpty() );
assertTrue( s.createQuery( "from Person" ).list().isEmpty() );
}
);
@ -173,13 +176,13 @@ public class SimpleInheritanceTest {
q.setSalary( new BigDecimal( 1000 ) );
s.save( q );
List result = s.createQuery( "from org.hibernate.orm.test.discriminator.Person where salary > 100" )
List result = s.createQuery( "from Person where salary > 100" )
.list();
assertThat( result.size(), is( 1 ) );
assertSame( result.get( 0 ), q );
result = s.createQuery(
"from org.hibernate.orm.test.discriminator.Person where salary > 100 or name like 'E%'" )
"from Person where salary > 100 or name like 'E%'" )
.list();
assertThat( result.size(), is( 2 ) );
@ -226,7 +229,7 @@ public class SimpleInheritanceTest {
assertTrue( pLoad instanceof HibernateProxy );
Person pGet = s.get( Person.class, employee.getId() );
Person pQuery = (Person) s.createQuery(
"from org.hibernate.orm.test.discriminator.Person where id = :id" )
"from Person where id = :id" )
.setParameter( "id", employee.getId() )
.uniqueResult();
@ -277,7 +280,7 @@ public class SimpleInheritanceTest {
s.evict( pLoad );
Employee pGet = (Employee) s.get( Person.class, employee.getId() );
Employee pQuery = (Employee) s.createQuery(
"from org.hibernate.orm.test.discriminator.Person where id = :id" )
"from Person where id = :id" )
.setParameter( "id", employee.getId() )
.uniqueResult();

View File

@ -4,7 +4,7 @@
* 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.discriminator.joined;
package org.hibernate.orm.test.mapping.inheritance.discriminator.joined;
/**
* @author Chris Cranford

View File

@ -4,7 +4,7 @@
* 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.discriminator.joined;
package org.hibernate.orm.test.mapping.inheritance.discriminator.joined;
import javax.persistence.Tuple;
@ -21,7 +21,7 @@ import org.assertj.core.api.Assertions;
* @author Steve Ebersole
*/
@DomainModel(
xmlMappings = "org/hibernate/orm/test/discriminator/joined/JoinedSubclassInheritance.hbm.xml"
xmlMappings = "org/hibernate/orm/test/mapping/inheritance/discriminator/joined/JoinedSubclassInheritance.hbm.xml"
)
@SessionFactory
public class DiscriminatorQueryUsageTests {

View File

@ -3,18 +3,18 @@
<!--
~ 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>.
~ 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
-->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
"-//Hibernate/Hibernate Mapping DTD 4.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-4.0.xsd">
<hibernate-mapping
package="org.hibernate.orm.test.discriminator.joined"
package="org.hibernate.orm.test.mapping.inheritance.discriminator.joined"
default-access="field">
<class name="org.hibernate.orm.test.discriminator.joined.ParentEntity" discriminator-value="pe">
<class name="ParentEntity" discriminator-value="pe">
<id name="id" type="integer">
<column name="id"/>
</id>
@ -24,7 +24,7 @@
<property name="type" insert="false" update="false" type="string"/>
</class>
<joined-subclass name="org.hibernate.orm.test.discriminator.joined.ChildEntity" discriminator-value="ce" extends="org.hibernate.orm.test.discriminator.joined.ParentEntity">
<joined-subclass name="ChildEntity" discriminator-value="ce" extends="ParentEntity">
<key>
<column name="id" />
</key>

View File

@ -1,10 +1,10 @@
/*
* 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>.
* 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.discriminator.joined;
package org.hibernate.orm.test.mapping.inheritance.discriminator.joined;
import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel;
@ -21,7 +21,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
*/
@TestForIssue(jiraKey = "HHH-11133")
@DomainModel(
xmlMappings = "org/hibernate/orm/test/discriminator/joined/JoinedSubclassInheritance.hbm.xml"
xmlMappings = "org/hibernate/orm/test/mapping/inheritance/discriminator/joined/JoinedSubclassInheritance.hbm.xml"
)
@SessionFactory
public class JoinedSubclassInheritanceTest {
@ -37,9 +37,7 @@ public class JoinedSubclassInheritanceTest {
@Test
public void testConfiguredDiscriminatorValue(SessionFactoryScope scope) {
final ChildEntity childEntity = new ChildEntity( 1, "Child" );
scope.inTransaction( session ->
session.save( childEntity )
);
scope.inTransaction( session -> session.save( childEntity ) );
scope.inTransaction( session -> {
ChildEntity ce = session.find( ChildEntity.class, 1 );

View File

@ -4,7 +4,7 @@
* 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.discriminator.joined;
package org.hibernate.orm.test.mapping.inheritance.discriminator.joined;
/**
* @author Chris Cranford

View File

@ -0,0 +1,56 @@
/*
* 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.mapping.inheritance.dynamic;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.tuple.DynamicMapInstantiator;
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.assertj.core.api.Assertions.assertThat;
/**
* @author Steve Ebersole
*/
@DomainModel( xmlMappings = "org/hibernate/orm/test/mapping/inheritance/dynamic/JoinedMappings.hbm.xml" )
@SessionFactory
public class DynamicJoinedInheritanceTests {
@Test
public void testLoading(SessionFactoryScope scope) {
scope.inTransaction( (session) -> {
final Map<String,?> entity = (Map<String, ?>) session.get( "Sub", 1 );
assertThat( entity ).isNotNull();
assertThat( entity.get( DynamicMapInstantiator.KEY ) ).isNotNull();
assertThat( entity.get( DynamicMapInstantiator.KEY ) ).isEqualTo( "Sub" );
} );
}
@BeforeEach
public void createTestData(SessionFactoryScope scope) {
scope.inTransaction( (session) -> {
final HashMap<Object, Object> entity = new HashMap<>();
entity.put( "id", 1 );
entity.put( "name", "sub" );
entity.put( "subText", "" );
session.save( "Sub", entity );
} );
}
@AfterEach
public void dropTestData(SessionFactoryScope scope) {
scope.inTransaction( (session) -> {
session.createQuery( "delete Sub" ).executeUpdate();
} );
}
}

View File

@ -0,0 +1,27 @@
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--
This mapping demonstrates content-based discrimination for the
table-per-hierarchy mapping strategy, using a formula
discriminator.
-->
<hibernate-mapping
package="org.hibernate.orm.test.mapping.inheritance.dynamic"
default-access="field">
<class abstract="true" entity-name="Base" table="t_base">
<id type="integer" />
<property name="name" type="string"/>
<joined-subclass entity-name="Sub" table="t_sub">
<key column="sub_id"/>
<property name="subText" type="string"/>
</joined-subclass>
</class>
</hibernate-mapping>

View File

@ -0,0 +1,13 @@
/*
* 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 for testing inheritance with dynamic entity models (MAP, entity-name)
*
* @author Steve Ebersole
*/
package org.hibernate.orm.test.mapping.inheritance.dynamic;

View File

@ -16,6 +16,11 @@ appender.unclosedSessionFactoryFile.fileName=target/tmp/log/UnclosedSessionFacto
appender.unclosedSessionFactoryFile.layout.type=PatternLayout
appender.unclosedSessionFactoryFile.layout.pattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
appender.ddl.type=Console
appender.ddl.name=DDL
appender.ddl.layout.type=PatternLayout
appender.ddl.layout.pattern=%d{ABSOLUTE} %5p %c:%L - %m%n
rootLogger.level=info
rootLogger.appenderRef.stdout.ref=STDOUT
@ -30,6 +35,7 @@ logger.tooling-schema-script-graph.name=org.hibernate.orm.tooling.schema.script.
logger.hbm2ddl.name=org.hibernate.tool.hbm2ddl
logger.hbm2ddl.level=trace
logger.testing-cache.name=org.hibernate.testing.cache
logger.testing-cache.level=debug

View File

@ -9,6 +9,11 @@ appender.stdout.name=STDOUT
appender.stdout.layout.type=PatternLayout
appender.stdout.layout.pattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n
appender.ddl.type=Console
appender.ddl.name=DDL
appender.ddl.layout.type=PatternLayout
appender.ddl.layout.pattern=%d{ABSOLUTE} %5p %c:%L - %m%n
rootLogger.level=info
rootLogger.appenderRef.stdout.ref=STDOUT
@ -18,13 +23,21 @@ logger.test.level=info
# SQL Logging - HHH-6833
logger.sql.name=org.hibernate.SQL
logger.sql.level=debug
logger.hbm2ddl.name=org.hibernate.tool.hbm2ddl
logger.hbm2ddl.level=debug
logger.hbm2ddl.level=trace
logger.hbm2ddl.appenderRef.stdout.ref=DDL
logger.type-basic-binder.name=org.hibernate.type.descriptor.jdbc.BasicBinder
logger.type-basic-binder.level=trace
logger.type-basic-extractor.name=org.hibernate.type.descriptor.jdbc.BasicExtractor
logger.type-basic-extractor.level=trace
logger.jdbc-bind.name=org.hibernate.orm.jdbc.bind
logger.jdbc-bind.level=trace
logger.jdbc-extract.name=org.hibernate.orm.jdbc.extract
logger.jdbc-extract.level=trace
logger.additional-jaxb-mapping-producer-impl.name=org.hibernate.envers.boot.internal.AdditionalJaxbMappingProducerImpl
logger.additional-jaxb-mapping-producer-impl.level=trace