diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java index b2dd2b44219a..2ea28fad2a9c 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java @@ -6,6 +6,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import org.hibernate.AssertionFailure; +import org.hibernate.MappingException; import org.hibernate.annotations.NotFoundAction; import org.hibernate.cache.MutableCacheKeyBuilder; import org.hibernate.engine.FetchStyle; @@ -24,6 +25,7 @@ import org.hibernate.mapping.Property; import org.hibernate.mapping.ToOne; import org.hibernate.mapping.Value; +import org.hibernate.metamodel.RepresentationMode; import org.hibernate.metamodel.UnsupportedMappingException; import org.hibernate.metamodel.mapping.AssociationKey; import org.hibernate.metamodel.mapping.AttributeMetadata; @@ -248,6 +250,27 @@ public ToOneAttributeMapping( declaringType, propertyAccess ); + + if ( entityMappingType.getRepresentationStrategy().getMode() == RepresentationMode.POJO ) { + // validate the type. + var declaredType = propertyAccess.getGetter().getReturnTypeClass(); + if ( !Object.class.equals( declaredType ) ) { + var targetType = entityMappingType.getMappedJavaType().getJavaTypeClass(); + if ( !declaredType.isAssignableFrom( targetType ) ) { + throw new MappingException( + String.format( + Locale.ROOT, + "To-one mapping [%s.%s] was mapped with targetEntity=`%s`, but the attribute is declared as `%s`", + declaringType.getNavigableRole().getFullPath(), + name, + targetType.getName(), + declaredType.getName() + ) + ); + } + } + } + sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( name ); isNullable = bootValue.isNullable(); isLazy = navigableRole.getParent().getParent() == null diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/manytoone/BadTargetTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/manytoone/BadTargetTests.java new file mode 100644 index 000000000000..40af0eae9ce0 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/manytoone/BadTargetTests.java @@ -0,0 +1,86 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.mapping.manytoone; + +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import org.hibernate.MappingException; +import org.hibernate.boot.MetadataSources; +import org.hibernate.boot.spi.MetadataImplementor; +import org.hibernate.testing.orm.junit.Jira; +import org.hibernate.testing.orm.junit.ServiceRegistry; +import org.hibernate.testing.orm.junit.ServiceRegistryScope; +import org.hibernate.testing.orm.junit.Setting; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.fail; +import static org.hibernate.cfg.SchemaToolingSettings.HBM2DDL_AUTO; + +/** + * @author Steve Ebersole + */ +@SuppressWarnings("JUnitMalformedDeclaration") +@Jira( "https://hibernate.atlassian.net/browse/HHH-7202" ) +@ServiceRegistry(settings = @Setting( name = HBM2DDL_AUTO, value = "create-drop" )) +public class BadTargetTests { + @Test + void testIt(ServiceRegistryScope registryScope) { + var model = (MetadataImplementor) new MetadataSources( registryScope.getRegistry() ) + .addAnnotatedClasses( Foo.class, Bar.class, Baz.class ) + .buildMetadata(); + try (var sf = model.buildSessionFactory()) { + fail( "Expecting a failure" ); + } + catch (MappingException expected) { + } + } + + @Entity(name="Foo") + @Table(name="foos") + public static class Foo { + @Id + private Integer id; + private String name; + @ManyToOne(targetEntity = Baz.class) + @JoinColumn(name = "bar_fk") + private Bar bar; + + public Foo() { + } + + public Foo(Integer id, String name, Bar bar) { + this.id = id; + this.name = name; + this.bar = bar; + } + } + + @Entity(name="Bar") + @Table(name="bars") + public static class Bar { + @Id + private Integer id; + private String name; + + public Bar() { + } + + public Bar(Integer id, String name) { + this.id = id; + this.name = name; + } + } + + @Entity(name="Baz") + @Table(name="Baz") + public static class Baz { + @Id + private Integer id; + private String name; + } +} diff --git a/hibernate-core/src/test/resources/org/hibernate/orm/test/quote/DataPoint.hbm.xml b/hibernate-core/src/test/resources/org/hibernate/orm/test/quote/DataPoint.hbm.xml index 393a55b0afa0..7ae7b1a446fc 100644 --- a/hibernate-core/src/test/resources/org/hibernate/orm/test/quote/DataPoint.hbm.xml +++ b/hibernate-core/src/test/resources/org/hibernate/orm/test/quote/DataPoint.hbm.xml @@ -45,7 +45,7 @@ - +