HHH-15884 - Clean-up EntityDiscriminatorMapping for API

HHH-15891 - Clean-up EntityVersionMapping for API
HHH-15892 - Clean-up EntityIdentifierMapping for API
This commit is contained in:
Steve Ebersole 2022-12-15 18:55:28 -06:00
parent e82c8fe911
commit ed4af59882
16 changed files with 223 additions and 80 deletions

View File

@ -0,0 +1,20 @@
/*
* 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;
import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping;
/**
* An "aggregated" composite identifier, which is another way to say that the
* identifier is represented as an {@linkplain jakarta.persistence.EmbeddedId embeddable}.
*
* @see jakarta.persistence.EmbeddedId
*
* @author Steve Ebersole
*/
public interface AggregatedIdentifierMapping extends SingleAttributeIdentifierMapping {
}

View File

@ -9,7 +9,7 @@ package org.hibernate.metamodel.mapping;
import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping; import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping;
/** /**
* Mapping for a simple identifier * Mapping for a simple, single-column identifier
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */

View File

@ -11,12 +11,17 @@ import org.hibernate.engine.internal.ForeignKeys;
import org.hibernate.engine.spi.IdentifierValue; import org.hibernate.engine.spi.IdentifierValue;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import jakarta.persistence.EmbeddedId;
import jakarta.persistence.Id;
import jakarta.persistence.IdClass;
/** /**
* Describes the mapping of an entity's identifier. * Describes the mapping of an entity's identifier.
* *
* @see jakarta.persistence.Id * @see Id
* @see jakarta.persistence.EmbeddedId * @see EmbeddedId
* @see Nature
*/ */
public interface EntityIdentifierMapping extends ValuedModelPart { public interface EntityIdentifierMapping extends ValuedModelPart {
@ -40,20 +45,23 @@ public interface EntityIdentifierMapping extends ValuedModelPart {
/** /**
* The strategy for distinguishing between detached and transient * The strategy for distinguishing between detached and transient
* state based on the identifier mapping * state based on the identifier mapping
*
* @see EntityVersionMapping#getUnsavedStrategy()
*/ */
IdentifierValue getUnsavedStrategy(); IdentifierValue getUnsavedStrategy();
/** /**
* Instantiate an instance of the identifier.
* *
* * @apiNote This is really only valid on {@linkplain CompositeIdentifierMapping composite identifiers}
* @return the entity identifier value
*
* @deprecated Use {@link #getIdentifier(Object)}
*/ */
@Deprecated Object instantiate();
Object getIdentifier(Object entity, SharedSessionContractImplementor session);
/**
* Extract the identifier from an instance of the entity
*/
Object getIdentifier(Object entity); Object getIdentifier(Object entity);
/** /**
* Return the identifier of the persistent or transient object, or throw * Return the identifier of the persistent or transient object, or throw
* an exception if the instance is "unsaved" * an exception if the instance is "unsaved"
@ -97,24 +105,39 @@ public interface EntityIdentifierMapping extends ValuedModelPart {
return id; return id;
} }
/**
* Inject an identifier value into an instance of the entity
*/
void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session); void setIdentifier(Object entity, Object id, SharedSessionContractImplementor session);
Object instantiate(); /**
* The style of identifier used.
*/
enum Nature { enum Nature {
/** /**
* Single column id * Simple, single-column identifier.
*
* @see Id
* @see BasicEntityIdentifierMapping
*/ */
SIMPLE, SIMPLE,
/** /**
* @see jakarta.persistence.EmbeddedId * An "aggregated" composite identifier, which is another way to say that the
* identifier is represented as an {@linkplain EmbeddedId embeddable}.
*
* @see EmbeddedId
* @see AggregatedIdentifierMapping
*/ */
COMPOSITE, COMPOSITE,
/** /**
* Composite identifier defined with multiple {@link jakarta.persistence.Id} * Composite identifier defined with multiple {@link Id}
* mappings. Often used in conjunction with an {@link jakarta.persistence.IdClass} * mappings. Often used in conjunction with an {@link IdClass}
*
* @see Id
* @see IdClass
* @see NonAggregatedIdentifierMapping
*/ */
VIRTUAL VIRTUAL
} }

View File

@ -8,7 +8,6 @@ package org.hibernate.metamodel.mapping;
import org.hibernate.engine.spi.VersionValue; import org.hibernate.engine.spi.VersionValue;
import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping; import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.VersionJavaType; import org.hibernate.type.descriptor.java.VersionJavaType;
/** /**
@ -24,7 +23,9 @@ public interface EntityVersionMapping extends BasicValuedModelPart {
/** /**
* The strategy for distinguishing between detached and transient * The strategy for distinguishing between detached and transient
* state based on the version mapping * state based on the version mapping.
*
* @see EntityIdentifierMapping#getUnsavedStrategy()
*/ */
VersionValue getUnsavedStrategy(); VersionValue getUnsavedStrategy();
@ -35,4 +36,9 @@ public interface EntityVersionMapping extends BasicValuedModelPart {
default VersionJavaType<?> getExpressibleJavaType() { default VersionJavaType<?> getExpressibleJavaType() {
return (VersionJavaType<?>) getMappedType().getMappedJavaType(); return (VersionJavaType<?>) getMappedType().getMappedJavaType();
} }
@Override
default AttributeMapping asAttributeMapping() {
return getVersionAttribute();
}
} }

View File

@ -16,7 +16,7 @@ import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable;
/** /**
* A "non-aggregated" composite identifier, which means that the entity itself * A "non-aggregated" composite identifier, which means that the entity itself
* does not define a singular representation of its identifier like an * does not define a singular representation of its identifier like an
* {@link jakarta.persistence.EmbeddedId} does. * {@linkplain AggregatedIdentifierMapping aggregated mapping} does.
* *
* An IdClass can be used to provide a simple, singular representation of the * An IdClass can be used to provide a simple, singular representation of the
* identifier for easier reference in API calls. JPA requires using an IdClass * identifier for easier reference in API calls. JPA requires using an IdClass
@ -73,6 +73,7 @@ public interface NonAggregatedIdentifierMapping extends CompositeIdentifierMappi
* Convenience method to iterate the attributes for this mapper's representation * Convenience method to iterate the attributes for this mapper's representation
*/ */
default void forEachAttribute(IndexedConsumer<SingularAttributeMapping> consumer) { default void forEachAttribute(IndexedConsumer<SingularAttributeMapping> consumer) {
//noinspection unchecked,rawtypes
getEmbeddedPart().getEmbeddableTypeDescriptor().forEachAttributeMapping( (IndexedConsumer) consumer ); getEmbeddedPart().getEmbeddableTypeDescriptor().forEachAttributeMapping( (IndexedConsumer) consumer );
} }
} }

View File

@ -47,6 +47,10 @@ import org.hibernate.type.BasicType;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
/** /**
* Mapping of a simple identifier
*
* @see jakarta.persistence.Id
*
* @author Andrea Boriero * @author Andrea Boriero
*/ */
public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMapping, FetchOptions { public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMapping, FetchOptions {
@ -96,6 +100,7 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
this.attributeName = attributeName; this.attributeName = attributeName;
this.rootTable = rootTable; this.rootTable = rootTable;
this.pkColumnName = pkColumnName; this.pkColumnName = pkColumnName;
//noinspection unchecked
this.idType = (BasicType<Object>) idType; this.idType = (BasicType<Object>) idType;
this.entityPersister = entityPersister; this.entityPersister = entityPersister;
@ -142,15 +147,6 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
return unsavedStrategy; return unsavedStrategy;
} }
@Override
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity );
if ( lazyInitializer != null ) {
return lazyInitializer.getIdentifier();
}
return propertyAccess.getGetter().get( entity );
}
@Override @Override
public Object getIdentifier(Object entity) { public Object getIdentifier(Object entity) {
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity ); final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity );

View File

@ -10,6 +10,7 @@ import java.util.function.BiConsumer;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.internal.AbstractCompositeIdentifierMapping; import org.hibernate.metamodel.internal.AbstractCompositeIdentifierMapping;
import org.hibernate.metamodel.mapping.AggregatedIdentifierMapping;
import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
@ -29,7 +30,7 @@ import org.hibernate.sql.results.graph.Fetchable;
*/ */
public class EmbeddedIdentifierMappingImpl public class EmbeddedIdentifierMappingImpl
extends AbstractCompositeIdentifierMapping extends AbstractCompositeIdentifierMapping
implements SingleAttributeIdentifierMapping { implements AggregatedIdentifierMapping {
private final String name; private final String name;
private final EmbeddableMappingType embeddableDescriptor; private final EmbeddableMappingType embeddableDescriptor;
private final PropertyAccess propertyAccess; private final PropertyAccess propertyAccess;
@ -83,15 +84,6 @@ public class EmbeddedIdentifierMappingImpl
getEmbeddableTypeDescriptor().applySqlSelections( navigablePath, tableGroup, creationState, selectionConsumer ); getEmbeddableTypeDescriptor().applySqlSelections( navigablePath, tableGroup, creationState, selectionConsumer );
} }
@Override
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity );
if ( lazyInitializer != null ) {
return lazyInitializer.getIdentifier();
}
return propertyAccess.getGetter().get( entity );
}
@Override @Override
public Object getIdentifier(Object entity) { public Object getIdentifier(Object entity) {
final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity ); final LazyInitializer lazyInitializer = HibernateProxy.extractLazyInitializer( entity );

View File

@ -178,11 +178,6 @@ public class InverseNonAggregatedIdentifierMapping extends EmbeddedAttributeMapp
return super.toSqlExpression( tableGroup, clause, walker, sqlAstCreationState ); return super.toSqlExpression( tableGroup, clause, walker, sqlAstCreationState );
} }
@Override
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
return getIdentifier( entity );
}
@Override @Override
public Object getIdentifier(Object entity) { public Object getIdentifier(Object entity) {
if ( hasContainingClass() ) { if ( hasContainingClass() ) {

View File

@ -64,7 +64,6 @@ import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.ManagedMappingType; import org.hibernate.metamodel.mapping.ManagedMappingType;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.ModelPartContainer; import org.hibernate.metamodel.mapping.ModelPartContainer;
import org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping;
import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.PropertyBasedMapping; import org.hibernate.metamodel.mapping.PropertyBasedMapping;
import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.metamodel.mapping.SelectableMapping;
@ -1386,12 +1385,12 @@ public class MappingModelCreationHelper {
SelectableMappings selectableMappings, SelectableMappings selectableMappings,
MappingModelCreationProcess creationProcess) { MappingModelCreationProcess creationProcess) {
final EmbeddableMappingType embeddableTypeDescriptor = modelPart.getEmbeddableTypeDescriptor(); final EmbeddableMappingType embeddableTypeDescriptor = modelPart.getEmbeddableTypeDescriptor();
if ( modelPart instanceof NonAggregatedIdentifierMapping ) { if ( modelPart instanceof org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping ) {
return new InverseNonAggregatedIdentifierMapping( return new InverseNonAggregatedIdentifierMapping(
keyDeclaringType, keyDeclaringType,
declaringTableGroupProducer, declaringTableGroupProducer,
selectableMappings, selectableMappings,
(NonAggregatedIdentifierMapping) modelPart, (org.hibernate.metamodel.mapping.NonAggregatedIdentifierMapping) modelPart,
embeddableTypeDescriptor, embeddableTypeDescriptor,
creationProcess creationProcess
); );

View File

@ -107,13 +107,6 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif
} }
} }
/**
* The entity whose identifier this mapping is the inverse of
*/
public EntityPersister getIdentifiedEntityDescriptor() {
return entityDescriptor;
}
@Override @Override
public EmbeddableMappingType getMappedType() { public EmbeddableMappingType getMappedType() {
return virtualIdEmbeddable; return virtualIdEmbeddable;
@ -209,11 +202,6 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif
return null; return null;
} }
@Override
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
return getIdentifier( entity );
}
@Override @Override
public Object getIdentifier(Object entity) { public Object getIdentifier(Object entity) {
if ( hasContainingClass() ) { if ( hasContainingClass() ) {

View File

@ -43,11 +43,6 @@ public class AnonymousTupleBasicEntityIdentifierMapping
return delegate.getUnsavedStrategy(); return delegate.getUnsavedStrategy();
} }
@Override
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
return delegate.getIdentifier( entity, session );
}
@Override @Override
public Object getIdentifier(Object entity) { public Object getIdentifier(Object entity) {
return delegate.getIdentifier( entity ); return delegate.getIdentifier( entity );

View File

@ -13,7 +13,6 @@ import org.hibernate.engine.spi.IdentifierValue;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping; import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.mapping.EmbeddableMappingType;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping; import org.hibernate.metamodel.mapping.internal.SingleAttributeIdentifierMapping;
import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.DomainType;
@ -37,7 +36,7 @@ public class AnonymousTupleEmbeddedEntityIdentifierMapping extends AnonymousTupl
modelParts, modelParts,
domainType, domainType,
componentName, componentName,
(EmbeddableValuedModelPart) delegate, delegate,
-1 -1
); );
this.delegate = delegate; this.delegate = delegate;
@ -53,11 +52,6 @@ public class AnonymousTupleEmbeddedEntityIdentifierMapping extends AnonymousTupl
return delegate.getUnsavedStrategy(); return delegate.getUnsavedStrategy();
} }
@Override
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
return delegate.getIdentifier( entity, session );
}
@Override @Override
public Object getIdentifier(Object entity) { public Object getIdentifier(Object entity) {
return delegate.getIdentifier( entity ); return delegate.getIdentifier( entity );

View File

@ -59,11 +59,6 @@ public class AnonymousTupleNonAggregatedEntityIdentifierMapping extends Anonymou
return delegate.getUnsavedStrategy(); return delegate.getUnsavedStrategy();
} }
@Override
public Object getIdentifier(Object entity, SharedSessionContractImplementor session) {
return delegate.getIdentifier( entity, session );
}
@Override @Override
public Object getIdentifier(Object entity) { public Object getIdentifier(Object entity) {
return delegate.getIdentifier( entity ); return delegate.getIdentifier( entity );

View File

@ -5073,10 +5073,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final EntityIdentifierMapping identifierMapping = entityValuedModelPart.getEntityMappingType() final EntityIdentifierMapping identifierMapping = entityValuedModelPart.getEntityMappingType()
.getIdentifierMapping(); .getIdentifierMapping();
associationKeyPart = identifierMapping; associationKeyPart = identifierMapping;
associationKey = identifierMapping.getIdentifier( associationKey = identifierMapping.getIdentifier( literal.getLiteralValue() );
literal.getLiteralValue(),
null
);
} }
if ( associationKeyPart instanceof BasicValuedMapping ) { if ( associationKeyPart instanceof BasicValuedMapping ) {
return new QueryLiteral<>( return new QueryLiteral<>(

View File

@ -0,0 +1,131 @@
/*
* 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;
import java.time.Instant;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityVersionMapping;
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
import org.hibernate.testing.orm.domain.StandardDomainModel;
import org.hibernate.testing.orm.domain.retail.CardPayment;
import org.hibernate.testing.orm.domain.retail.CashPayment;
import org.hibernate.testing.orm.domain.retail.DomesticVendor;
import org.hibernate.testing.orm.domain.retail.ForeignVendor;
import org.hibernate.testing.orm.domain.retail.Payment;
import org.hibernate.testing.orm.domain.retail.Product;
import org.hibernate.testing.orm.domain.retail.Vendor;
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.Test;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests access to {@link MappingMetamodel} as API and SPI contracts
*
* @author Steve Ebersole
*/
@DomainModel(standardModels = StandardDomainModel.RETAIL)
@SessionFactory(exportSchema = false)
public class MappingModelAccessTests {
@Test
public void testUnwrapAccess(SessionFactoryScope scope) {
final SessionFactoryImplementor sf = scope.getSessionFactory();
final MappingMetamodel mappingMetamodel = sf.unwrap( MappingMetamodel.class );
assertThat( mappingMetamodel ).isNotNull();
final MappingMetamodelImplementor mappingMetamodelImplementor = sf.unwrap( MappingMetamodelImplementor.class );
assertThat( mappingMetamodelImplementor ).isSameAs( mappingMetamodel );
}
@Test
void testEntityMappingAccess(SessionFactoryScope scope) {
final SessionFactoryImplementor sf = scope.getSessionFactory();
final MappingMetamodel mappingMetamodel = sf.unwrap( MappingMetamodel.class );
final EntityMappingType productMapping = mappingMetamodel.getEntityDescriptor( Product.class );
assertThat( productMapping ).isNotNull();
final EntityIdentifierMapping productIdMapping = productMapping.getIdentifierMapping();
assertThat( productIdMapping ).isNotNull();
assertThat( productIdMapping.getJavaType().getJavaTypeClass() ).isEqualTo( Integer.class );
final EntityVersionMapping productVersionMapping = productMapping.getVersionMapping();
assertThat( productVersionMapping ).isNotNull();
assertThat( productVersionMapping.getVersionAttribute().getAttributeName() ).isEqualTo( "version" );
assertThat( productVersionMapping.getVersionAttribute().getJavaType().getJavaTypeClass() ).isEqualTo( Instant.class );
assertThat( productVersionMapping.asAttributeMapping() ).isSameAs( productVersionMapping.getVersionAttribute() );
}
@Test
void testJoinedSubclassInheritance(SessionFactoryScope scope) {
final SessionFactoryImplementor sf = scope.getSessionFactory();
final MappingMetamodel mappingMetamodel = sf.unwrap( MappingMetamodel.class );
final EntityMappingType paymentMapping = mappingMetamodel.getEntityDescriptor( Payment.class );
final EntityMappingType cardPaymentMapping = mappingMetamodel.getEntityDescriptor( CardPayment.class );
final EntityMappingType cashPaymentMapping = mappingMetamodel.getEntityDescriptor( CashPayment.class );
final EntityDiscriminatorMapping discriminatorMapping = paymentMapping.getDiscriminatorMapping();
assertThat( discriminatorMapping )
.isSameAs( cardPaymentMapping.getDiscriminatorMapping() )
.isSameAs( cashPaymentMapping.getDiscriminatorMapping() );
assertThat( discriminatorMapping.isPhysical() ).isFalse();
assertThat( discriminatorMapping.isVirtual() ).isTrue();
assertThat( discriminatorMapping.getJavaType().getJavaTypeClass() ).isEqualTo( Class.class );
assertThat( discriminatorMapping.getJdbcMapping().getJavaTypeDescriptor().getJavaTypeClass() ).isEqualTo( Class.class );
assertThat( discriminatorMapping.getJdbcMapping().getJdbcJavaType().getJavaTypeClass() ).isEqualTo( Integer.class );
assertThat( paymentMapping.getDiscriminatorValue() ).isEqualTo( 0 );
assertThat( cashPaymentMapping.getDiscriminatorValue() ).isEqualTo( 1 );
assertThat( cardPaymentMapping.getDiscriminatorValue() ).isEqualTo( 2 );
assertThat( discriminatorMapping.resolveDiscriminatorValue( 0 ).getIndicatedEntity() ).isEqualTo( paymentMapping );
assertThat( discriminatorMapping.resolveDiscriminatorValue( 1 ).getIndicatedEntity() ).isEqualTo( cashPaymentMapping );
assertThat( discriminatorMapping.resolveDiscriminatorValue( 2 ).getIndicatedEntity() ).isEqualTo( cardPaymentMapping );
assertThat( discriminatorMapping.resolveDiscriminatorValue( 3 ) ).isNull();
}
@Test
void testSingleTableInheritance(SessionFactoryScope scope) {
final SessionFactoryImplementor sf = scope.getSessionFactory();
final MappingMetamodel mappingMetamodel = sf.unwrap( MappingMetamodel.class );
final EntityMappingType vendorMapping = mappingMetamodel.getEntityDescriptor( Vendor.class );
final EntityMappingType domesticVendorMapping = mappingMetamodel.getEntityDescriptor( DomesticVendor.class );
final EntityMappingType foreignVendorMapping = mappingMetamodel.getEntityDescriptor( ForeignVendor.class );
final EntityDiscriminatorMapping discriminatorMapping = vendorMapping.getDiscriminatorMapping();
assertThat( discriminatorMapping )
.isSameAs( domesticVendorMapping.getDiscriminatorMapping() )
.isSameAs( foreignVendorMapping.getDiscriminatorMapping() );
assertThat( discriminatorMapping.isPhysical() ).isTrue();
assertThat( discriminatorMapping.isVirtual() ).isTrue();
assertThat( discriminatorMapping.getJavaType().getJavaTypeClass() ).isEqualTo( Class.class );
assertThat( discriminatorMapping.getJdbcMapping().getJavaTypeDescriptor().getJavaTypeClass() ).isEqualTo( Class.class );
assertThat( discriminatorMapping.getJdbcMapping().getJdbcJavaType().getJavaTypeClass() ).isEqualTo( String.class );
assertThat( vendorMapping.getDiscriminatorValue() ).isEqualTo( "Vendor" );
assertThat( domesticVendorMapping.getDiscriminatorValue() ).isEqualTo( "domestic" );
assertThat( foreignVendorMapping.getDiscriminatorValue() ).isEqualTo( "foreign" );
assertThat( discriminatorMapping.resolveDiscriminatorValue( "Vendor" ).getIndicatedEntity() ).isEqualTo( vendorMapping );
assertThat( discriminatorMapping.resolveDiscriminatorValue( "domestic" ).getIndicatedEntity() ).isEqualTo( domesticVendorMapping );
assertThat( discriminatorMapping.resolveDiscriminatorValue( "foreign" ).getIndicatedEntity() ).isEqualTo( foreignVendorMapping );
assertThat( discriminatorMapping.resolveDiscriminatorValue( "invalid" ) ).isNull();
}
}

View File

@ -6,14 +6,20 @@
*/ */
package org.hibernate.testing.orm.domain.retail; package org.hibernate.testing.orm.domain.retail;
import java.time.Instant;
import java.util.UUID; import java.util.UUID;
import javax.money.MonetaryAmount; import javax.money.MonetaryAmount;
import org.hibernate.annotations.CurrentTimestamp;
import org.hibernate.annotations.NaturalId;
import jakarta.persistence.Access;
import jakarta.persistence.AccessType;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.Id; import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne; import jakarta.persistence.ManyToOne;
import jakarta.persistence.Version;
import org.hibernate.annotations.NaturalId;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -27,6 +33,11 @@ public class Product {
private MonetaryAmount currentSellPrice; private MonetaryAmount currentSellPrice;
@Access( AccessType.FIELD )
@Version
@CurrentTimestamp
private Instant version;
public Product() { public Product() {
} }