natural-id + not-found

https://hibernate.atlassian.net/browse/HHH-17197 - Add check for illegal combo of to-one + natural-id + not-found
https://hibernate.atlassian.net/browse/HHH-17196 - Documentation for @NaturalId should be more explicit about non-nullability

(cherry picked from commit 6c2e04381d)
This commit is contained in:
Steve Ebersole 2023-09-26 08:54:36 -05:00
parent 8f4afa625f
commit f5bdf08d25
4 changed files with 25 additions and 32 deletions

View File

@ -67,6 +67,7 @@ dependencies {
annotationProcessor( libraries.logging_annotations )
testCompile( libraries.junit )
testCompile( libraries.assertj )
testCompile( libraries.byteman )
testCompile( libraries.byteman_install )
testCompile( libraries.byteman_bmunit )

View File

@ -13,6 +13,7 @@ ext {
h2Version = '1.4.196'
bytemanVersion = '4.0.16' //Compatible with JDK 17
jnpVersion = '5.0.6.CR1'
assertjVersion = "3.22.0"
hibernateValidatorVersion = '6.0.22.Final'
hibernateCommonsVersion = '5.0.5.Final'
@ -103,6 +104,7 @@ ext {
log4j2: "org.apache.logging.log4j:log4j-core:2.17.1",
junit: "junit:junit:${junitVersion}",
assertj: "org.assertj:assertj-core:${assertjVersion}",
byteman: "org.jboss.byteman:byteman:${bytemanVersion}",
byteman_install: "org.jboss.byteman:byteman-install:${bytemanVersion}",
byteman_bmunit: "org.jboss.byteman:byteman-bmunit:${bytemanVersion}",

View File

@ -19,8 +19,6 @@ import java.util.Set;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.annotations.NotFoundAction;
import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cfg.NotYetImplementedException;
@ -32,15 +30,10 @@ import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.mapping.Component;
import org.hibernate.mapping.GeneratorCreator;
import org.hibernate.mapping.ManyToOne;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.Subclass;
import org.hibernate.mapping.ToOne;
import org.hibernate.mapping.Value;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.tuple.GenerationTiming;
import org.hibernate.tuple.IdentifierProperty;
@ -240,7 +233,7 @@ public class EntityMetamodel implements Serializable {
}
if ( prop.isNaturalIdentifier() ) {
verifyNaturalIdProperty( property );
verifyNaturalIdProperty( prop );
naturalIdNumbers.add( i );
if ( prop.isUpdateable() ) {
foundUpdateableNaturalIdProperty = true;
@ -672,7 +665,7 @@ public class EntityMetamodel implements Serializable {
final Value value = property.getValue();
if ( value instanceof ManyToOne ) {
final ManyToOne toOne = (ManyToOne) value;
if ( toOne.getNotFoundAction() == NotFoundAction.IGNORE ) {
if ( toOne.isIgnoreNotFound() ) {
throw new MappingException(
"Attribute marked as natural-id can not also be a not-found association - "
+ propertyName( property )
@ -681,8 +674,10 @@ public class EntityMetamodel implements Serializable {
}
else if ( value instanceof Component ) {
final Component component = (Component) value;
for ( Property componentProperty : component.getProperties() ) {
verifyNaturalIdProperty( componentProperty );
//noinspection unchecked
final Iterator<Property> properties = component.getPropertyIterator();
while ( properties.hasNext() ) {
verifyNaturalIdProperty( properties.next() );
}
}
}

View File

@ -4,7 +4,14 @@
* 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.naturalid;
package org.hibernate.test.naturalid;
import javax.persistence.Embeddable;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.MappingException;
import org.hibernate.SessionFactory;
@ -12,31 +19,20 @@ import org.hibernate.annotations.NaturalId;
import org.hibernate.annotations.NotFound;
import org.hibernate.annotations.NotFoundAction;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.ServiceRegistryScope;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Embeddable;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.fail;
import static org.junit.Assert.fail;
/**
* @author Steve Ebersole
*/
@ServiceRegistry
public class ValidationTests {
public class ValidationTests extends BaseUnitTestCase {
@Test
void checkManyToOne(ServiceRegistryScope registryScope) {
final StandardServiceRegistry registry = registryScope.getRegistry();
final MetadataSources metadataSources = new MetadataSources( registry )
public void checkManyToOne() {
final MetadataSources metadataSources = new MetadataSources()
.addAnnotatedClass( Thing1.class )
.addAnnotatedClass( Thing2.class );
try (final SessionFactory sessionFactory = metadataSources.buildMetadata().buildSessionFactory(); ) {
@ -49,9 +45,8 @@ public class ValidationTests {
}
@Test
void checkEmbeddable(ServiceRegistryScope registryScope) {
final StandardServiceRegistry registry = registryScope.getRegistry();
final MetadataSources metadataSources = new MetadataSources( registry )
public void checkEmbeddable() {
final MetadataSources metadataSources = new MetadataSources()
.addAnnotatedClass( Thing1.class )
.addAnnotatedClass( Thing3.class )
.addAnnotatedClass( Container.class );