diff --git a/documentation/src/main/asciidoc/userguide/appendices/Configurations.adoc b/documentation/src/main/asciidoc/userguide/appendices/Configurations.adoc index b68e21e51a..d3a4445cbd 100644 --- a/documentation/src/main/asciidoc/userguide/appendices/Configurations.adoc +++ b/documentation/src/main/asciidoc/userguide/appendices/Configurations.adoc @@ -383,6 +383,9 @@ This setting applies to Oracle Dialect only, and it specifies whether `byte[]` o `*hibernate.type.preferred_boolean_jdbc_type_code*` (e.g. `-7` for `java.sql.Types.BIT`):: Global setting identifying the preferred JDBC type code for storing boolean values. The fallback is to ask the Dialect. +`*hibernate.type.preferred_duration_jdbc_type_code*` (e.g. `2` for `java.sql.Types.NUMERIC` or `3` for `java.sql.Types.DECIMAL`):: +Global setting identifying the preferred JDBC type code for storing duration values. The fallback is `3100` for `org.hibernate.types.SqlTypes.INTERVAL_SECOND`. + ==== Bean Validation options `*jakarta.persistence.validation.factory*` (e.g. `jakarta.validation.ValidationFactory` implementation):: Specify the `javax.validation.ValidationFactory` implementation to use for Bean Validation. diff --git a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java index b8bbdee61a..95cb407ae0 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/SessionFactoryOptionsBuilder.java @@ -212,6 +212,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions { private Boolean useOfJdbcNamedParametersEnabled; private boolean namedQueryStartupCheckingEnabled; private final int preferredSqlTypeCodeForBoolean; + private final int preferredSqlTypeCodeForDuration; private final TimeZoneStorageStrategy defaultTimeZoneStorageStrategy; // Caching @@ -415,6 +416,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions { this.namedQueryStartupCheckingEnabled = cfgService.getSetting( QUERY_STARTUP_CHECKING, BOOLEAN, true ); this.preferredSqlTypeCodeForBoolean = ConfigurationHelper.getPreferredSqlTypeCodeForBoolean( serviceRegistry ); + this.preferredSqlTypeCodeForDuration = ConfigurationHelper.getPreferredSqlTypeCodeForDuration( serviceRegistry ); this.defaultTimeZoneStorageStrategy = context.getMetadataBuildingOptions().getDefaultTimeZoneStorage(); final RegionFactory regionFactory = serviceRegistry.getService( RegionFactory.class ); @@ -1188,6 +1190,11 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions { return preferredSqlTypeCodeForBoolean; } + @Override + public int getPreferredSqlTypeCodeForDuration() { + return preferredSqlTypeCodeForDuration; + } + @Override public TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy() { return defaultTimeZoneStorageStrategy; diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java index 6e1526d84c..a590b9812c 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/AbstractDelegatingSessionFactoryOptions.java @@ -437,6 +437,11 @@ public class AbstractDelegatingSessionFactoryOptions implements SessionFactoryOp return delegate.getPreferredSqlTypeCodeForBoolean(); } + @Override + public int getPreferredSqlTypeCodeForDuration() { + return delegate.getPreferredSqlTypeCodeForDuration(); + } + @Override public TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy() { return delegate.getDefaultTimeZoneStorageStrategy(); diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataBuildingContext.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataBuildingContext.java index b828f7ef2a..fa264d278d 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataBuildingContext.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/MetadataBuildingContext.java @@ -55,6 +55,10 @@ public interface MetadataBuildingContext { return ConfigurationHelper.getPreferredSqlTypeCodeForBoolean( getBootstrapContext().getServiceRegistry() ); } + default int getPreferredSqlTypeCodeForDuration() { + return ConfigurationHelper.getPreferredSqlTypeCodeForDuration( getBootstrapContext().getServiceRegistry() ); + } + TypeDefinitionRegistry getTypeDefinitionRegistry(); /** diff --git a/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java index 0e8f3a8dc2..c6d14d11f7 100644 --- a/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java +++ b/hibernate-core/src/main/java/org/hibernate/boot/spi/SessionFactoryOptions.java @@ -300,6 +300,8 @@ public interface SessionFactoryOptions extends QueryEngineOptions { int getPreferredSqlTypeCodeForBoolean(); + int getPreferredSqlTypeCodeForDuration(); + TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy(); FormatMapper getJsonFormatMapper(); diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java index 4053ff924c..348987d8d5 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/AvailableSettings.java @@ -2483,6 +2483,14 @@ public interface AvailableSettings { */ String PREFERRED_BOOLEAN_JDBC_TYPE_CODE = "hibernate.type.preferred_boolean_jdbc_type_code"; + /** + * Specifies the preferred JDBC type code for storing duration values. When no + * type code is explicitly specified, {@link org.hibernate.type.SqlTypes#INTERVAL_SECOND} is used. + * + * @since 6.0 + */ + String PREFERRED_DURATION_JDBC_TYPE_CODE = "hibernate.type.preferred_duration_jdbc_type_code"; + /** * Specifies a {@link org.hibernate.type.FormatMapper} used for for JSON serialization * and deserialization, either: diff --git a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/BasicValueBinder.java b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/BasicValueBinder.java index 68195c1fe1..44855ee761 100644 --- a/hibernate-core/src/main/java/org/hibernate/cfg/annotations/BasicValueBinder.java +++ b/hibernate-core/src/main/java/org/hibernate/cfg/annotations/BasicValueBinder.java @@ -214,6 +214,11 @@ public class BasicValueBinder implements JdbcTypeIndicators { return buildingContext.getPreferredSqlTypeCodeForBoolean(); } + @Override + public int getPreferredSqlTypeCodeForDuration() { + return buildingContext.getPreferredSqlTypeCodeForDuration(); + } + @Override public boolean isNationalized() { return isNationalized; diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/config/ConfigurationHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/config/ConfigurationHelper.java index ddb0bb36ab..7f2c665ecb 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/util/config/ConfigurationHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/config/ConfigurationHelper.java @@ -20,6 +20,7 @@ import org.hibernate.engine.config.spi.StandardConverters; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.collections.ArrayHelper; +import org.hibernate.type.SqlTypes; /** * Collection of helper methods for dealing with configuration settings. @@ -528,4 +529,12 @@ public final class ConfigurationHelper { .getPreferredSqlTypeCodeForBoolean(); } + public static synchronized int getPreferredSqlTypeCodeForDuration(StandardServiceRegistry serviceRegistry) { + return serviceRegistry.getService( ConfigurationService.class ).getSetting( + AvailableSettings.PREFERRED_DURATION_JDBC_TYPE_CODE, + StandardConverters.INTEGER, + SqlTypes.INTERVAL_SECOND + ); + } + } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java b/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java index 71619539c4..57a17661a5 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/BasicValue.java @@ -679,6 +679,11 @@ public class BasicValue extends SimpleValue implements JdbcTypeIndicators, Resol return getBuildingContext().getPreferredSqlTypeCodeForBoolean(); } + @Override + public int getPreferredSqlTypeCodeForDuration() { + return getBuildingContext().getPreferredSqlTypeCodeForDuration(); + } + @Override public TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy() { if ( timeZoneStorageType != null ) { diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java index da19b2183f..9396f9ffcf 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java @@ -584,7 +584,12 @@ public abstract class BaseSqmToSqlAstConverter extends Base return creationContext.getSessionFactory().getSessionFactoryOptions().getPreferredSqlTypeCodeForBoolean(); } -// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + @Override + public int getPreferredSqlTypeCodeForDuration() { + return creationContext.getSessionFactory().getSessionFactoryOptions().getPreferredSqlTypeCodeForDuration(); + } + + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // FromClauseAccess @Override diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DurationJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DurationJavaType.java index 746b03c32d..578d62b2e1 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DurationJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DurationJavaType.java @@ -54,7 +54,7 @@ public class DurationJavaType extends AbstractClassJavaType { @Override public JdbcType getRecommendedJdbcType(JdbcTypeIndicators context) { - return context.getTypeConfiguration().getJdbcTypeRegistry().getDescriptor( SqlTypes.INTERVAL_SECOND ); + return context.getTypeConfiguration().getJdbcTypeRegistry().getDescriptor( context.getPreferredSqlTypeCodeForDuration() ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JdbcTypeIndicators.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JdbcTypeIndicators.java index a30c343775..66dfde0251 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JdbcTypeIndicators.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/jdbc/JdbcTypeIndicators.java @@ -11,6 +11,7 @@ import jakarta.persistence.EnumType; import jakarta.persistence.TemporalType; import org.hibernate.TimeZoneStorageStrategy; +import org.hibernate.type.SqlTypes; import org.hibernate.type.descriptor.java.BasicJavaType; import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry; import org.hibernate.type.spi.TypeConfiguration; @@ -72,6 +73,16 @@ public interface JdbcTypeIndicators { return Types.BOOLEAN; } + /** + * When mapping a duration type to the database what is the preferred SQL type code to use? + *

+ * Specifically names the key into the + * {@link JdbcTypeRegistry}. + */ + default int getPreferredSqlTypeCodeForDuration() { + return SqlTypes.INTERVAL_SECOND; + } + /** * Useful for resolutions based on column length. E.g. choosing between a VARCHAR (String) and a CHAR(1) (Character/char) */ diff --git a/hibernate-core/src/main/java/org/hibernate/type/spi/TypeConfiguration.java b/hibernate-core/src/main/java/org/hibernate/type/spi/TypeConfiguration.java index 21f38feade..340407acf6 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/spi/TypeConfiguration.java +++ b/hibernate-core/src/main/java/org/hibernate/type/spi/TypeConfiguration.java @@ -351,11 +351,6 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable { public TypeConfiguration getTypeConfiguration() { return typeConfiguration; } - - @Override - public int getPreferredSqlTypeCodeForBoolean() { - return SqlTypes.BOOLEAN; - } }; public Scope(TypeConfiguration typeConfiguration) {