From ebfaf1c707319a0f0d1f04c70f6b8d52488da2c7 Mon Sep 17 00:00:00 2001 From: Andrea Boriero Date: Tue, 4 Jul 2023 17:39:09 +0200 Subject: [PATCH] HHH-16586 When merging a persisted entity with a null Version, Hibernate treats entity as transient instead of throwing an Exception --- .../entity/AbstractEntityPersister.java | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 12799f0a3c..b321a04888 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -39,6 +39,7 @@ import org.hibernate.LazyInitializationException; import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.MappingException; +import org.hibernate.PropertyValueException; import org.hibernate.QueryException; import org.hibernate.Remove; import org.hibernate.StaleObjectStateException; @@ -3926,20 +3927,29 @@ public abstract class AbstractEntityPersister // let this take precedence if defined, since it works for // assigned identifiers final Object version = getVersion( entity ); - final Boolean result = versionMapping.getUnsavedStrategy().isUnsaved( version ); - if ( result != null ) { - if ( result && version == null && session.getPersistenceContext().hasLoadContext() ) { - // check if we're currently loading this entity instance, the version - // will be null but the entity cannot be considered transient - final EntityKey entityKey = new EntityKey( id, this ); - final LoadingEntityEntry loadingEntityEntry = session.getPersistenceContext() - .getLoadContexts() - .findLoadingEntityEntry( entityKey ); - if ( loadingEntityEntry != null && loadingEntityEntry.getEntityInstance() == entity ) { - return false; + final Boolean isUnsaved = versionMapping.getUnsavedStrategy().isUnsaved( version ); + if ( isUnsaved != null ) { + if ( isUnsaved ) { + if ( version == null && session.getPersistenceContext().hasLoadContext() ) { + // check if we're currently loading this entity instance, the version + // will be null but the entity cannot be considered transient + final LoadingEntityEntry loadingEntityEntry = session.getPersistenceContext() + .getLoadContexts() + .findLoadingEntityEntry( new EntityKey( id, this ) ); + if ( loadingEntityEntry != null && loadingEntityEntry.getEntityInstance() == entity ) { + return false; + } + } + final Boolean unsaved = identifierMapping.getUnsavedStrategy().isUnsaved( id ); + if ( unsaved != null && !unsaved ) { + throw new PropertyValueException( + "Detached entity with generated id '" + id + "' has an uninitialized version value '" + version + "'", + getEntityName(), + getVersionColumnName() + ); } } - return result; + return isUnsaved; } }