HHH-12125 - Support @GeneratedValue without explicit generator definition
This commit is contained in:
parent
9a75fa8d97
commit
99428251c4
|
@ -16,6 +16,7 @@ import org.hibernate.boot.model.IdGeneratorStrategyInterpreter;
|
|||
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.BinderHelper;
|
||||
import org.hibernate.id.IncrementGenerator;
|
||||
import org.hibernate.id.MultipleHiLoPerTableGenerator;
|
||||
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||
import org.hibernate.id.SequenceHiLoGenerator;
|
||||
|
@ -109,13 +110,17 @@ public class IdGeneratorInterpreterImpl implements IdGeneratorStrategyInterprete
|
|||
}
|
||||
default: {
|
||||
// AUTO
|
||||
|
||||
if ( "increment".equalsIgnoreCase( context.getGeneratedValueGeneratorName() ) ) {
|
||||
return IncrementGenerator.class.getName();
|
||||
}
|
||||
|
||||
final Class javaType = context.getIdType();
|
||||
if ( UUID.class.isAssignableFrom( javaType ) ) {
|
||||
return UUIDGenerator.class.getName();
|
||||
}
|
||||
else {
|
||||
return "native";
|
||||
}
|
||||
|
||||
return "native";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -217,13 +222,17 @@ public class IdGeneratorInterpreterImpl implements IdGeneratorStrategyInterprete
|
|||
}
|
||||
default: {
|
||||
// AUTO
|
||||
|
||||
if ( "increment".equalsIgnoreCase( context.getGeneratedValueGeneratorName() ) ) {
|
||||
return IncrementGenerator.class.getName();
|
||||
}
|
||||
|
||||
final Class javaType = context.getIdType();
|
||||
if ( UUID.class.isAssignableFrom( javaType ) ) {
|
||||
return UUIDGenerator.class.getName();
|
||||
}
|
||||
else {
|
||||
return org.hibernate.id.enhanced.SequenceStyleGenerator.class.getName();
|
||||
}
|
||||
|
||||
return org.hibernate.id.enhanced.SequenceStyleGenerator.class.getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
package org.hibernate.boot.model;
|
||||
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
import javax.persistence.TableGenerator;
|
||||
|
@ -16,8 +17,17 @@ import javax.persistence.TableGenerator;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface IdGeneratorStrategyInterpreter {
|
||||
public static interface GeneratorNameDeterminationContext {
|
||||
public Class getIdType();
|
||||
interface GeneratorNameDeterminationContext {
|
||||
/**
|
||||
* The Java type of the attribute defining the id whose value is to
|
||||
* be generated.
|
||||
*/
|
||||
Class getIdType();
|
||||
|
||||
/**
|
||||
* The {@link GeneratedValue#generator()} name.
|
||||
*/
|
||||
String getGeneratedValueGeneratorName();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,8 +35,18 @@ public interface IdGeneratorStrategyInterpreter {
|
|||
* GenerationType, returning {@code null} to indicate that this interpreter
|
||||
* did not have a match and that any additional resolutions should be performed.
|
||||
*
|
||||
* @apiNote Not really a great name as it is a bit confusing. What is really
|
||||
* being resolved here is the name of the
|
||||
* {@link org.hibernate.id.IdentifierGenerator} to use. This is (generally)
|
||||
* different than the {@link GeneratedValue#generator()} name for the
|
||||
* {@link GeneratedValue} that is the source of the passed {@link GenerationType}.
|
||||
* For implementations that need it, the {@link GeneratedValue#generator()}
|
||||
* is passed as part of the `context`.
|
||||
*
|
||||
* @param generationType The {@link javax.persistence.GeneratedValue#strategy} value
|
||||
* @param context The context for resolution (method parameter object)
|
||||
*
|
||||
* @return The {@link org.hibernate.id.IdentifierGenerator} name (FQN, short name, etc)
|
||||
*/
|
||||
String determineGeneratorName(GenerationType generationType, GeneratorNameDeterminationContext context);
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ import javax.persistence.EmbeddedId;
|
|||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.IdClass;
|
||||
import javax.persistence.InheritanceType;
|
||||
|
@ -146,11 +145,8 @@ import org.hibernate.cfg.annotations.QueryBinder;
|
|||
import org.hibernate.cfg.annotations.SimpleValueBinder;
|
||||
import org.hibernate.cfg.annotations.TableBinder;
|
||||
import org.hibernate.engine.OptimisticLockStyle;
|
||||
import org.hibernate.engine.config.spi.ConfigurationService;
|
||||
import org.hibernate.engine.config.spi.StandardConverters;
|
||||
import org.hibernate.engine.spi.FilterDefinition;
|
||||
import org.hibernate.id.PersistentIdentifierGenerator;
|
||||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.loader.PropertyPath;
|
||||
|
@ -2386,7 +2382,7 @@ public final class AnnotationBinder {
|
|||
|
||||
GeneratedValue generatedValue = idXProperty.getAnnotation( GeneratedValue.class );
|
||||
String generatorType = generatedValue != null
|
||||
? generatorType( generatedValue.strategy(), buildingContext, entityXClass )
|
||||
? generatorType( generatedValue, buildingContext, entityXClass )
|
||||
: "assigned";
|
||||
String generatorName = generatedValue != null
|
||||
? generatedValue.generator()
|
||||
|
@ -2410,11 +2406,11 @@ public final class AnnotationBinder {
|
|||
}
|
||||
|
||||
public static String generatorType(
|
||||
GenerationType generatorEnum,
|
||||
GeneratedValue generatedValueAnn,
|
||||
final MetadataBuildingContext buildingContext,
|
||||
final XClass javaTypeXClass) {
|
||||
return buildingContext.getBuildingOptions().getIdGenerationTypeInterpreter().determineGeneratorName(
|
||||
generatorEnum,
|
||||
generatedValueAnn.strategy(),
|
||||
new IdGeneratorStrategyInterpreter.GeneratorNameDeterminationContext() {
|
||||
Class javaType = null;
|
||||
@Override
|
||||
|
@ -2426,6 +2422,11 @@ public final class AnnotationBinder {
|
|||
}
|
||||
return javaType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGeneratedValueGeneratorName() {
|
||||
return generatedValueAnn.generator();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
@ -2739,7 +2740,7 @@ public final class AnnotationBinder {
|
|||
|
||||
GeneratedValue generatedValue = property.getAnnotation( GeneratedValue.class );
|
||||
String generatorType = generatedValue != null
|
||||
? generatorType( generatedValue.strategy(), buildingContext, property.getType() )
|
||||
? generatorType( generatedValue, buildingContext, property.getType() )
|
||||
: "assigned";
|
||||
String generator = generatedValue != null ? generatedValue.generator() : BinderHelper.ANNOTATION_STRING_DEFAULT;
|
||||
|
||||
|
|
|
@ -1735,6 +1735,10 @@ public interface AvailableSettings {
|
|||
* True/false setting indicating whether the value specified for {@link GeneratedValue#generator()}
|
||||
* should be used as the sequence/table name when no matching {@link javax.persistence.SequenceGenerator}
|
||||
* or {@link javax.persistence.TableGenerator} is found.
|
||||
*
|
||||
* The default value is `true` meaning that {@link GeneratedValue#generator()} will be used as the
|
||||
* sequence/table name by default. Users migrating from earlier versions using the legacy
|
||||
* `hibernate_sequence` name should disable this setting,
|
||||
*/
|
||||
String PREFER_GENERATOR_NAME_AS_DEFAULT_SEQUENCE_NAME = "hibernate.model.generator_name_as_sequence_name";
|
||||
}
|
||||
|
|
|
@ -877,7 +877,19 @@ public class BinderHelper {
|
|||
else {
|
||||
strategyName = generationInterpreter.determineGeneratorName(
|
||||
generationType,
|
||||
() -> buildingContext.getBuildingOptions().getReflectionManager().toClass( idXProperty.getType() )
|
||||
new IdGeneratorStrategyInterpreter.GeneratorNameDeterminationContext() {
|
||||
@Override
|
||||
public Class getIdType() {
|
||||
return buildingContext.getBuildingOptions()
|
||||
.getReflectionManager()
|
||||
.toClass( idXProperty.getType() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGeneratedValueGeneratorName() {
|
||||
return generatedValueAnn.generator();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -280,7 +280,7 @@ public class SequenceStyleGenerator
|
|||
|
||||
String fallbackSequenceName = DEF_SEQUENCE_NAME;
|
||||
final Boolean preferGeneratorNameAsDefaultName = serviceRegistry.getService( ConfigurationService.class )
|
||||
.getSetting( AvailableSettings.PREFER_GENERATOR_NAME_AS_DEFAULT_SEQUENCE_NAME, StandardConverters.BOOLEAN );
|
||||
.getSetting( AvailableSettings.PREFER_GENERATOR_NAME_AS_DEFAULT_SEQUENCE_NAME, StandardConverters.BOOLEAN, true );
|
||||
if ( preferGeneratorNameAsDefaultName != null && preferGeneratorNameAsDefaultName ) {
|
||||
final String generatorName = params.getProperty( IdentifierGenerator.GENERATOR_NAME );
|
||||
if ( StringHelper.isNotEmpty( generatorName ) ) {
|
||||
|
|
|
@ -394,7 +394,7 @@ public class TableGenerator implements PersistentIdentifierGenerator, Configurab
|
|||
if ( tableName == null ) {
|
||||
tableName = DEF_TABLE;
|
||||
final Boolean preferGeneratorNameAsDefaultName = serviceRegistry.getService( ConfigurationService.class )
|
||||
.getSetting( AvailableSettings.PREFER_GENERATOR_NAME_AS_DEFAULT_SEQUENCE_NAME, StandardConverters.BOOLEAN );
|
||||
.getSetting( AvailableSettings.PREFER_GENERATOR_NAME_AS_DEFAULT_SEQUENCE_NAME, StandardConverters.BOOLEAN, true );
|
||||
if ( preferGeneratorNameAsDefaultName != null && preferGeneratorNameAsDefaultName ) {
|
||||
final String generatorName = params.getProperty( IdentifierGenerator.GENERATOR_NAME );
|
||||
if ( StringHelper.isNotEmpty( generatorName ) ) {
|
||||
|
|
|
@ -12,6 +12,7 @@ import javax.persistence.GenerationType;
|
|||
import javax.persistence.Id;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||
|
@ -19,6 +20,7 @@ import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
|||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.id.IdentifierGenerator;
|
||||
import org.hibernate.id.IncrementGenerator;
|
||||
import org.hibernate.id.enhanced.SequenceStyleGenerator;
|
||||
import org.hibernate.id.enhanced.TableGenerator;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
|
@ -33,6 +35,9 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
|||
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
|
||||
|
||||
/**
|
||||
* Tests of various aspects of {@link GeneratedValue} handling in regards to determining
|
||||
* the {@link IdentifierGenerator} to use
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class GeneratedValueTests extends BaseUnitTestCase {
|
||||
|
@ -60,7 +65,9 @@ public class GeneratedValueTests extends BaseUnitTestCase {
|
|||
|
||||
@Test
|
||||
public void testImplicitSequenceGenerator() {
|
||||
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().build();
|
||||
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder()
|
||||
.applySetting( AvailableSettings.PREFER_GENERATOR_NAME_AS_DEFAULT_SEQUENCE_NAME, "false" )
|
||||
.build();
|
||||
final Metadata bootModel = new MetadataSources( ssr )
|
||||
.addAnnotatedClass( ImplicitSequenceGeneratorEntity.class )
|
||||
.buildMetadata();
|
||||
|
@ -81,9 +88,7 @@ public class GeneratedValueTests extends BaseUnitTestCase {
|
|||
|
||||
@Test
|
||||
public void testImplicitSequenceGeneratorGeneratorName() {
|
||||
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder()
|
||||
.applySetting( AvailableSettings.PREFER_GENERATOR_NAME_AS_DEFAULT_SEQUENCE_NAME, "true" )
|
||||
.build();
|
||||
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().build();
|
||||
final Metadata bootModel = new MetadataSources( ssr )
|
||||
.addAnnotatedClass( ImplicitSequenceGeneratorEntity.class )
|
||||
.buildMetadata();
|
||||
|
@ -105,7 +110,9 @@ public class GeneratedValueTests extends BaseUnitTestCase {
|
|||
|
||||
@Test
|
||||
public void testExplicitSequenceGeneratorImplicitName() {
|
||||
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().build();
|
||||
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder()
|
||||
.applySetting( AvailableSettings.PREFER_GENERATOR_NAME_AS_DEFAULT_SEQUENCE_NAME, "false" )
|
||||
.build();
|
||||
final Metadata bootModel = new MetadataSources( ssr )
|
||||
.addAnnotatedClass( ExplicitSequenceGeneratorImplicitNameEntity.class )
|
||||
.buildMetadata();
|
||||
|
@ -127,9 +134,8 @@ public class GeneratedValueTests extends BaseUnitTestCase {
|
|||
|
||||
@Test
|
||||
public void testExplicitSequenceGeneratorImplicitNamePreferGeneratorName() {
|
||||
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder()
|
||||
.applySetting( AvailableSettings.PREFER_GENERATOR_NAME_AS_DEFAULT_SEQUENCE_NAME, "true" )
|
||||
.build();
|
||||
// this should be the default behavior
|
||||
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().build();
|
||||
final Metadata bootModel = new MetadataSources( ssr )
|
||||
.addAnnotatedClass( ExplicitSequenceGeneratorImplicitNameEntity.class )
|
||||
.buildMetadata();
|
||||
|
@ -171,6 +177,42 @@ public class GeneratedValueTests extends BaseUnitTestCase {
|
|||
assertThat( tableGenerator.getIncrementSize(), is( 50 ) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExplicitIncrementGenerator() {
|
||||
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().build();
|
||||
final Metadata bootModel = new MetadataSources( ssr )
|
||||
.addAnnotatedClass( ExplicitIncrementGeneratorEntity.class )
|
||||
.buildMetadata();
|
||||
final PersistentClass entityMapping = bootModel.getEntityBinding( ExplicitIncrementGeneratorEntity.class.getName() );
|
||||
final IdentifierGenerator generator = entityMapping.getIdentifier().createIdentifierGenerator(
|
||||
bootModel.getIdentifierGeneratorFactory(),
|
||||
ssr.getService( JdbcEnvironment.class ).getDialect(),
|
||||
null,
|
||||
null,
|
||||
(RootClass) entityMapping
|
||||
);
|
||||
|
||||
assertTyping( IncrementGenerator.class, generator );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testImplicitIncrementGenerator() {
|
||||
final StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().build();
|
||||
final Metadata bootModel = new MetadataSources( ssr )
|
||||
.addAnnotatedClass( ImplicitIncrementGeneratorEntity.class )
|
||||
.buildMetadata();
|
||||
final PersistentClass entityMapping = bootModel.getEntityBinding( ImplicitIncrementGeneratorEntity.class.getName() );
|
||||
final IdentifierGenerator generator = entityMapping.getIdentifier().createIdentifierGenerator(
|
||||
bootModel.getIdentifierGeneratorFactory(),
|
||||
ssr.getService( JdbcEnvironment.class ).getDialect(),
|
||||
null,
|
||||
null,
|
||||
(RootClass) entityMapping
|
||||
);
|
||||
|
||||
assertTyping( IncrementGenerator.class, generator );
|
||||
}
|
||||
|
||||
@Entity
|
||||
public static class ExplicitGeneratorEntity {
|
||||
/**
|
||||
|
@ -216,4 +258,27 @@ public class GeneratedValueTests extends BaseUnitTestCase {
|
|||
public Integer id;
|
||||
public String name;
|
||||
}
|
||||
|
||||
@Entity
|
||||
public static class ExplicitIncrementGeneratorEntity {
|
||||
/**
|
||||
* This entity does not have explicit {@link javax.persistence.TableGenerator} defined
|
||||
*/
|
||||
@Id
|
||||
@GeneratedValue( strategy = GenerationType.AUTO, generator = "increment" )
|
||||
@GenericGenerator( name = "increment", strategy = "increment" )
|
||||
public Integer id;
|
||||
public String name;
|
||||
}
|
||||
|
||||
@Entity
|
||||
public static class ImplicitIncrementGeneratorEntity {
|
||||
/**
|
||||
* This entity does not have explicit {@link javax.persistence.TableGenerator} defined
|
||||
*/
|
||||
@Id
|
||||
@GeneratedValue( strategy = GenerationType.AUTO, generator = "increment" )
|
||||
public Integer id;
|
||||
public String name;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue