HHH-17472 Add assigned identifiers support for generated values

This commit is contained in:
Marco Belladelli 2023-11-29 17:17:03 +01:00 committed by Christian Beikov
parent 26e4ad52c7
commit f13eb7549d
4 changed files with 43 additions and 14 deletions

View File

@ -155,6 +155,20 @@ public interface IdentifierGenerator extends BeforeExecutionGenerator, Exportabl
return INSERT_ONLY;
}
/**
* Determine if this generator allows identifier values to be manually assigned to the entity
* instance before persisting it. This is useful when, for example, needing existing assigned
* values to be used as identifiers and falling back to generated values by default.
*
* @return {@code true} if this generator allows pre-assigned identifier values,
* {@code false} otherwise (default).
*
* @since 6.5
*/
default boolean allowAssignedIdentifiers() {
return false;
}
/**
* Check if JDBC batch inserts are supported.
*

View File

@ -130,11 +130,6 @@ public class IdentifierGeneratorUtil {
params
);
if ( generator.generatedOnExecution() && generator instanceof BeforeExecutionGenerator ) {
// support mixed-timing generators
simpleValue.setNullValue( "undefined" );
}
return generator;
}

View File

@ -77,6 +77,7 @@ import org.hibernate.jpa.internal.PersistenceUnitUtilImpl;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.RootClass;
import org.hibernate.mapping.SimpleValue;
import org.hibernate.metadata.CollectionMetadata;
import org.hibernate.metamodel.internal.RuntimeMetamodelsImpl;
import org.hibernate.metamodel.mapping.JdbcMapping;
@ -460,7 +461,11 @@ public class SessionFactoryImpl extends QueryParameterBindingTypeResolverImpl im
(RootClass) model
);
if ( generator instanceof IdentifierGenerator ) {
( (IdentifierGenerator) generator ).initialize( sqlStringGenerationContext );
final IdentifierGenerator identifierGenerator = (IdentifierGenerator) generator;
identifierGenerator.initialize( sqlStringGenerationContext );
if ( identifierGenerator.allowAssignedIdentifiers() ) {
( (SimpleValue) model.getIdentifier() ).setNullValue( "undefined" );
}
}
generators.put( model.getEntityName(), generator );
} );

View File

@ -9,6 +9,7 @@ package org.hibernate.orm.test.idgen.userdefined;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.util.EnumSet;
import java.util.Properties;
import java.util.concurrent.ThreadLocalRandom;
import org.hibernate.annotations.GenericGenerator;
@ -23,8 +24,11 @@ import org.hibernate.generator.BeforeExecutionGenerator;
import org.hibernate.generator.EventType;
import org.hibernate.generator.EventTypeSets;
import org.hibernate.generator.OnExecutionGenerator;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.id.IdentityGenerator;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.Type;
import org.hibernate.testing.orm.junit.DialectFeatureChecks;
import org.hibernate.testing.orm.junit.DomainModel;
@ -43,6 +47,7 @@ import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hibernate.generator.EventTypeSets.INSERT_ONLY;
/**
* @author Marco Belladelli
@ -255,15 +260,11 @@ public class MixedTimingGeneratorsTest {
}
}
public static class IdentityOrAssignedGenerator extends IdentityGenerator implements BeforeExecutionGenerator {
public static class IdentityOrAssignedGenerator extends IdentityGenerator implements IdentifierGenerator {
@Override
public Object generate(
SharedSessionContractImplementor session,
Object owner,
Object currentValue,
EventType eventType) {
final EntityPersister entityPersister = session.getEntityPersister( null, owner );
return entityPersister.getIdentifier( owner, session );
public Object generate(SharedSessionContractImplementor session, Object object) {
final EntityPersister entityPersister = session.getEntityPersister( null, object );
return entityPersister.getIdentifier( object, session );
}
@Override
@ -275,6 +276,20 @@ public class MixedTimingGeneratorsTest {
public boolean generatedOnExecution(Object owner, SharedSessionContractImplementor session) {
return generate( session, owner, null, null ) == null;
}
@Override
public boolean allowAssignedIdentifiers() {
return true;
}
@Override
public EnumSet<EventType> getEventTypes() {
return INSERT_ONLY;
}
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) {
}
}
public static class IdentityOrRandomGenerator extends IdentityGenerator implements BeforeExecutionGenerator {