* Add SqlTypes as analogy to java.sql.Types containing constants for Hibernate specified types

* Add FormatMapper for a pluggable JSON serialization and deserialization strategy
* Add native UUID type support for H2, Cockroach, PostgreSQL
* Add native INET type support for Cockroach, PostgreSQL
* Add native JSON type support for MySQL, Cockroach, PostgreSQL
* Add native INTERVAL SECOND type support for H2, Cockroach, PostgreSQL
* Add fallback JdbcTypes for new SqlTypes
* Register column types for new SqlTypes
* Add support for BasicTypeReference in TypedParameterValue
* Fix a lot of method signatures with respect to type parameter issues
* Fix CustomType, UserType and EnhancedUserType with respect to type parameters
* Get rid of StringRepresentableType and some other unused deprecated methods
This commit is contained in:
Christian Beikov 2021-10-15 13:28:26 +02:00
parent 541302a511
commit a4e406a54e
198 changed files with 3150 additions and 1303 deletions

View File

@ -125,10 +125,10 @@ Java and SQL data types. Hibernate attempts to determine the correct conversion
type attribute is not specified in the mapping, by using Java reflection to determine the Java type of the declared
property and using a default mapping type for that Java type.
In some cases this automatic detection might not chose the default you expect or need, as seen with the
`date` property. Hibernate cannot know if the property, which is of type `java.util.Date`, should map to a SQL
In some cases this automatic detection might not choose the default you expect or need, as seen with the
`date` property. Hibernate cannot know if the property, which is of type `java.util.Date`, should map to an SQL
_DATE_, _TIME_, or _TIMESTAMP_ datatype. Full date and time information is preserved by mapping the property to
the _timestamp_ converter, which identifies the converter class `org.hibernate.type.TimestampType`.
the _timestamp_ converter, which identifies the converter as declared by `org.hibernate.type.StandardBasicTypes.TIMESTAMP`.
TIP: Hibernate determines the mapping type using reflection when the mapping files are processed. This process adds
overhead in terms of time and resources. If startup performance is important, consider explicitly defining the type

View File

@ -406,6 +406,9 @@ Unless specified, the JDBC Driver uses the default JVM time zone. If a different
`*hibernate.dialect.oracle.prefer_long_raw*` (e.g. `true` or `false` (default value))::
This setting applies to Oracle Dialect only, and it specifies whether `byte[]` or `Byte[]` arrays should be mapped to the deprecated `LONG RAW` (when this configuration property value is `true`) or to a `BLOB` column type (when this configuration property value is `false`).
`*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.
==== Bean Validation options
`*jakarta.persistence.validation.factory*` (e.g. `jakarta.validation.ValidationFactory` implementation)::
Specify the `javax.validation.ValidationFactory` implementation to use for Bean Validation.
@ -435,6 +438,16 @@ Setting to identify an `org.hibernate.CustomEntityDirtinessStrategy` to use.
`*hibernate.default_entity_mode*` (e.g. `pojo` (default value) or `dynamic-map`)::
Default `EntityMode` for entity representation for all sessions opened from this `SessionFactory`, defaults to `pojo`.
`*hibernate.type.json_format_mapper*` (e.g. A fully-qualified class name, an instance, or a `Class` object reference)::
Names a https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/type/FormatMapper.html[`FormatMapper`] implementation to be applied to the `SessionFactory` for JSON serialization and deserialization.
+
Can reference a
`FormatMapper` instance,
`FormatMapper` implementation `Class` reference,
`FormatMapper` implementation class name (fully-qualified class name) or
one of the following short hand constants `jackson` or `jsonb`.
By default the first of the possible providers that is available in the runtime is used, according to the listing order.
[[configurations-bytecode-enhancement]]
=== Bytecode Enhancement Properties

View File

@ -115,11 +115,11 @@ See the <<chapters/query/spatial/Spatial.adoc#spatial,Spatial>> chapter for more
We said before that a Hibernate type is not a Java type, nor an SQL type, but that it understands both and performs the marshalling between them.
But looking at the basic type mappings from the previous examples,
how did Hibernate know to use its `org.hibernate.type.StringType` for mapping for `java.lang.String` attributes,
or its `org.hibernate.type.IntegerType` for mapping `java.lang.Integer` attributes?
how did Hibernate know to use its `org.hibernate.type.StandardBasicTypes.STRING` for mapping for `java.lang.String` attributes,
or its `org.hibernate.type.StandardBasicTypes.INTEGER` for mapping `java.lang.Integer` attributes?
The answer lies in a service inside Hibernate called the `org.hibernate.type.BasicTypeRegistry`, which maintains a
map of `org.hibernate.type.BasicType` instances keyed by a name.
map of `org.hibernate.type.BasicType` and `org.hibernate.type.BasicTypeReference` instances keyed by a name.
We will see later, in the <<basic-type-annotation>> section, that we can explicitly tell Hibernate which BasicType to use for a particular attribute.
But first, let's explore how implicit resolution works and how applications can adjust the implicit resolution.

View File

@ -272,7 +272,7 @@ In other words, `INSERT` statements are inherently non-polymorphic.
The SELECT statement can be any valid HQL select query, but the return types must match the types expected by the INSERT.
Hibernate verifies the return types during query compilation, instead of expecting the database to check it.
Problems might result from Hibernate types which are equivalent, rather than equal.
One such example is a mismatch between a property defined as an `org.hibernate.type.DateType` and a property defined as an `org.hibernate.type.TimestampType`,
One such example is a mismatch between a property defined as an `org.hibernate.type.StandardBasicTypes.DATE` and a property defined as an `org.hibernate.type.StandardBasicTypes.TIMESTAMP`,
even though the database may not make a distinction, or may be capable of handling the conversion.
If id property is not specified in the `properties_list`,

View File

@ -612,7 +612,7 @@ In other words, `INSERT` statements are inherently non-polymorphic.
`select_statement` can be any valid HQL select query, with the caveat that the return types must match the types expected by the insert.
Currently, this is checked during query compilation rather than allowing the check to delegate to the database.
This may cause problems between Hibernate Types which are _equivalent_ as opposed to __equal__.
For example, this might lead to issues with mismatches between an attribute mapped as a `org.hibernate.type.DateType` and an attribute defined as a `org.hibernate.type.TimestampType`,
For example, this might lead to issues with mismatches between an attribute mapped as a `org.hibernate.type.StandardBasicTypes.DATE` and an attribute defined as a `org.hibernate.type.StandardBasicTypes.TIMESTAMP`,
even though the database might not make a distinction or might be able to handle the conversion.
For the id attribute, the insert statement gives you two options.

View File

@ -6,18 +6,21 @@
*/
package org.hibernate.userguide.mapping.basic;
import java.sql.Types;
import java.time.Duration;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import org.hibernate.metamodel.MappingMetamodel;
import org.hibernate.metamodel.mapping.AttributeMapping;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.jdbc.AdjustableJdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptorIndicators;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
import org.hibernate.type.spi.TypeConfiguration;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
@ -45,7 +48,18 @@ public class DurationMappingTests {
final BasicAttributeMapping duration = (BasicAttributeMapping) entityDescriptor.findAttributeMapping( "duration" );
final JdbcMapping jdbcMapping = duration.getJdbcMapping();
assertThat( jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo( Duration.class ) );
assertThat( jdbcMapping.getJdbcTypeDescriptor(), is( jdbcTypeRegistry.getDescriptor( Types.NUMERIC ) ) );
final JdbcType intervalType = jdbcTypeRegistry.getDescriptor( SqlTypes.INTERVAL_SECOND );
final JdbcType realType;
if ( intervalType instanceof AdjustableJdbcType ) {
realType = ((AdjustableJdbcType) intervalType).resolveIndicatedType(
() -> domainModel.getTypeConfiguration(),
jdbcMapping.getJavaTypeDescriptor()
);
}
else {
realType = intervalType;
}
assertThat( jdbcMapping.getJdbcTypeDescriptor(), is( realType ) );
scope.inTransaction(
(session) -> {

View File

@ -90,6 +90,7 @@ ext {
jakarta_validator: "org.hibernate.validator:hibernate-validator:${hibernateValidatorJakartaVersion}",
jakarta_el: 'org.glassfish:jakarta.el:4.0.1',
jakarta_inject: 'jakarta.inject:jakarta.inject-api:2.0.0',
jakarta_jsonb: 'jakarta.json.bind:jakarta.json.bind-api:2.0.0',
// javax
jpa: "javax.persistence:javax.persistence-api:${project.jpaVersion}",
@ -121,6 +122,7 @@ ext {
// jaxb task
jackson: 'com.fasterxml.jackson.core:jackson-databind:2.13.0',
geolatte: "org.geolatte:geolatte-geom:${geolatteVersion}",
// Animal Sniffer Ant Task and Java 1.6 API signature file

View File

@ -20,6 +20,7 @@ import org.hibernate.community.dialect.sequence.CUBRIDSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.IntervalType;
import org.hibernate.query.SemanticException;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
@ -378,7 +379,7 @@ public class CUBRIDDialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
switch (unit) {
case NANOSECOND:
return "adddate(?3,interval (?2)/1e6 millisecond)";

View File

@ -26,6 +26,7 @@ import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.query.IntervalType;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.sql.ast.SqlAstTranslator;
@ -193,7 +194,7 @@ public class CacheDialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
switch (unit) {
case NANOSECOND:
case NATIVE:

View File

@ -11,6 +11,7 @@ import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.dialect.BooleanDecoder;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.TimeZoneSupport;
import org.hibernate.query.IntervalType;
import org.hibernate.query.NullOrdering;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.function.CommonFunctionFactory;
@ -426,7 +427,7 @@ public class FirebirdDialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
switch ( unit ) {
case NATIVE:
return "dateadd((?2) millisecond to ?3)";

View File

@ -25,6 +25,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.query.FetchClauseType;
import org.hibernate.query.IntervalType;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryOptions;
@ -308,7 +309,7 @@ public class IngresDialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
return "timestampadd(?1,?2,?3)";
}

View File

@ -20,6 +20,7 @@ import org.hibernate.community.dialect.sequence.MimerSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.IntervalType;
import org.hibernate.query.SemanticException;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
@ -207,7 +208,7 @@ public class MimerSQLDialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
switch ( unit ) {
case NATIVE:
case NANOSECOND:

View File

@ -19,6 +19,7 @@ import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.query.IntervalType;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.TrimSpec;
import org.hibernate.query.spi.QueryEngine;
@ -226,7 +227,7 @@ public class RDMSOS2200Dialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
switch (unit) {
case NANOSECOND:
return "timestampadd('SQL_TSI_FRAC_SECOND',(?2)/1e3,?3)";

View File

@ -36,6 +36,7 @@ import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.mapping.Column;
import org.hibernate.query.IntervalType;
import org.hibernate.query.NullOrdering;
import org.hibernate.query.SemanticException;
import org.hibernate.query.TemporalUnit;
@ -166,7 +167,7 @@ public class SQLiteDialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
final String function = temporalType == TemporalType.DATE ? "date" : "datetime";
switch ( unit ) {
case NANOSECOND:

View File

@ -27,6 +27,7 @@ import org.hibernate.mapping.Column;
import org.hibernate.mapping.Index;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.query.IntervalType;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryOptions;
@ -217,7 +218,7 @@ public class TeradataDialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
//TODO: TOTALLY UNTESTED CODE!
switch ( unit ) {
case NANOSECOND:

View File

@ -21,6 +21,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.query.IntervalType;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.mutation.internal.idtable.AfterUseAction;
@ -169,7 +170,7 @@ public class TimesTenDialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
switch (unit) {
case NANOSECOND:
case NATIVE:

View File

@ -43,6 +43,9 @@ dependencies {
compileOnly libraries.jakarta_validation
compileOnly libraries.jakarta_cdi
compileOnly libraries.jackson
compileOnly libraries.jakarta_jsonb
testImplementation project(':hibernate-testing')
testImplementation project(':hibernate-ant')
testImplementation libraries.shrinkwrap_api
@ -65,6 +68,7 @@ dependencies {
testRuntimeOnly libraries.byteBuddy
testRuntimeOnly libraries.jakarta_weld
testRuntimeOnly libraries.wildfly_transaction_client
testRuntimeOnly libraries.jackson
testAnnotationProcessor project( ':hibernate-jpamodelgen' )
@ -212,5 +216,6 @@ tasks.withType( Test.class ).each { test ->
test.include 'org/hibernate/bytecode/internal/bytebuddy/**'
test.include 'org/hibernate/event/service/internal/**'
test.include 'org/hibernate/tool/schema/internal/**'
// test.include '**/*'
}

View File

@ -74,6 +74,9 @@ import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.stat.Statistics;
import org.hibernate.tuple.entity.EntityTuplizer;
import org.hibernate.tuple.entity.EntityTuplizerFactory;
import org.hibernate.type.FormatMapper;
import org.hibernate.type.JacksonJsonFormatMapper;
import org.hibernate.type.JsonBJsonFormatMapper;
import static org.hibernate.cfg.AvailableSettings.ACQUIRE_CONNECTIONS;
import static org.hibernate.cfg.AvailableSettings.ALLOW_JTA_TRANSACTION_ACCESS;
@ -158,6 +161,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
// integration
private Object beanManagerReference;
private Object validatorFactoryReference;
private FormatMapper jsonFormatMapper;
// SessionFactory behavior
private boolean jpaBootstrap;
@ -301,6 +305,10 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
AvailableSettings.JPA_VALIDATION_FACTORY,
configurationSettings.get( AvailableSettings.JAKARTA_VALIDATION_FACTORY )
);
this.jsonFormatMapper = determineJsonFormatMapper(
configurationSettings.get( AvailableSettings.JSON_FORMAT_MAPPER ),
strategySelector
);
this.sessionFactoryName = (String) configurationSettings.get( SESSION_FACTORY_NAME );
this.sessionFactoryNameAlsoJndiName = cfgService.getSetting(
@ -799,7 +807,31 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
return PhysicalConnectionHandlingMode.interpret( effectiveAcquisitionMode, effectiveReleaseMode );
}
private static FormatMapper determineJsonFormatMapper(Object setting, StrategySelector strategySelector) {
return strategySelector.resolveDefaultableStrategy(
FormatMapper.class,
setting,
(Callable<FormatMapper>) () -> {
try {
// Force initialization of the instance
JacksonJsonFormatMapper.INSTANCE.hashCode();
return JacksonJsonFormatMapper.INSTANCE;
}
catch (NoClassDefFoundError ex) {
// Ignore
}
try {
// Force initialization of the instance
JsonBJsonFormatMapper.INSTANCE.hashCode();
return JsonBJsonFormatMapper.INSTANCE;
}
catch (NoClassDefFoundError ex) {
// Ignore
}
return null;
}
);
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -1220,6 +1252,11 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
public TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy() {
return defaultTimeZoneStorageStrategy;
}
@Override
public FormatMapper getJsonFormatMapper() {
return jsonFormatMapper;
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// In-flight mutation access

View File

@ -177,8 +177,8 @@ public class TypeDefinition implements Serializable {
injectParameters( typeInstance, combinedTypeParameters );
if ( typeInstance instanceof UserType ) {
final UserType userType = (UserType) typeInstance;
final CustomType customType = new CustomType( userType, typeConfiguration );
final UserType<Object> userType = (UserType<Object>) typeInstance;
final CustomType<Object> customType = new CustomType<>( userType, typeConfiguration );
return new UserTypeResolution( customType, null, combinedTypeParameters );
}

View File

@ -20,14 +20,14 @@ import org.hibernate.type.descriptor.jdbc.JdbcType;
* @author Steve Ebersole
*/
public class EnumeratedValueResolution<E extends Enum<E>> implements BasicValue.Resolution<E> {
private final CustomType enumTypeMapping;
private final CustomType<Object> enumTypeMapping;
private final JavaType<E> domainJtd;
private final JavaType<?> jdbcJtd;
private final JdbcType jdbcType;
private final EnumValueConverter<E,?> valueConverter;
public EnumeratedValueResolution(
CustomType enumTypeMapping,
CustomType<Object> enumTypeMapping,
JavaType<E> domainJtd,
JavaType<?> jdbcJtd,
JdbcType jdbcType,

View File

@ -25,6 +25,7 @@ import org.hibernate.type.AdjustableBasicType;
import org.hibernate.type.BasicType;
import org.hibernate.type.CustomType;
import org.hibernate.type.SerializableType;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.java.BasicJavaType;
import org.hibernate.type.descriptor.java.EnumJavaTypeDescriptor;
import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
@ -34,7 +35,6 @@ import org.hibernate.type.descriptor.java.TemporalJavaTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptorIndicators;
import org.hibernate.type.descriptor.jdbc.ObjectJdbcType;
import org.hibernate.type.descriptor.jdbc.TinyIntJdbcType;
import org.hibernate.type.spi.TypeConfiguration;
/**
@ -266,8 +266,8 @@ public class InferredBasicValueResolver {
}
@SuppressWarnings("rawtypes")
public static InferredBasicValueResolution fromEnum(
EnumJavaTypeDescriptor enumJavaDescriptor,
public static <E extends Enum<E>> InferredBasicValueResolution fromEnum(
EnumJavaTypeDescriptor<E> enumJavaDescriptor,
BasicJavaType explicitJavaType,
JdbcType explicitJdbcType,
JdbcTypeDescriptorIndicators stdIndicators,
@ -304,14 +304,13 @@ public class InferredBasicValueResolver {
relationalJtd
);
//noinspection unchecked
final org.hibernate.type.EnumType legacyEnumType = new org.hibernate.type.EnumType(
final org.hibernate.type.EnumType<E> legacyEnumType = new org.hibernate.type.EnumType<>(
enumJavaDescriptor.getJavaTypeClass(),
valueConverter,
typeConfiguration
);
final CustomType legacyEnumTypeWrapper = new CustomType( legacyEnumType, typeConfiguration );
final CustomType<E> legacyEnumTypeWrapper = new CustomType<>( legacyEnumType, typeConfiguration );
final JdbcMapping jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve( relationalJtd, jdbcType );
@ -343,7 +342,9 @@ public class InferredBasicValueResolver {
relationalJtd = typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( Integer.class );
}
final JdbcType jdbcType = explicitJdbcType != null ? explicitJdbcType : TinyIntJdbcType.INSTANCE;
final JdbcType jdbcType = explicitJdbcType != null
? explicitJdbcType
: typeConfiguration.getJdbcTypeDescriptorRegistry().getDescriptor( SqlTypes.TINYINT );
//noinspection unchecked
final OrdinalEnumValueConverter valueConverter = new OrdinalEnumValueConverter(
@ -352,14 +353,13 @@ public class InferredBasicValueResolver {
relationalJtd
);
//noinspection unchecked
final org.hibernate.type.EnumType legacyEnumType = new org.hibernate.type.EnumType(
final org.hibernate.type.EnumType<E> legacyEnumType = new org.hibernate.type.EnumType<>(
enumJavaDescriptor.getJavaTypeClass(),
valueConverter,
typeConfiguration
);
final CustomType legacyEnumTypeWrapper = new CustomType( legacyEnumType, typeConfiguration );
final CustomType<E> legacyEnumTypeWrapper = new CustomType<>( legacyEnumType, typeConfiguration );
final JdbcMapping jdbcMapping = typeConfiguration.getBasicTypeRegistry().resolve( relationalJtd, jdbcType );

View File

@ -21,7 +21,7 @@ import org.hibernate.type.descriptor.jdbc.JdbcType;
* @author Steve Ebersole
*/
public class UserTypeResolution implements BasicValue.Resolution {
private final CustomType userTypeAdapter;
private final CustomType<Object> userTypeAdapter;
private final MutabilityPlan mutabilityPlan;
/**
@ -31,7 +31,7 @@ public class UserTypeResolution implements BasicValue.Resolution {
private final Properties combinedTypeParameters;
public UserTypeResolution(
CustomType userTypeAdapter,
CustomType<Object> userTypeAdapter,
MutabilityPlan explicitMutabilityPlan,
Properties combinedTypeParameters) {
this.userTypeAdapter = userTypeAdapter;

View File

@ -24,25 +24,23 @@ import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptorIndicators;
*/
public class ValueConverterTypeAdapter<J> extends AbstractSingleColumnStandardBasicType<J> {
private final String description;
private final BasicValueConverter<J,?> converter;
private final BasicValueConverter<J, Object> converter;
@SuppressWarnings("rawtypes")
private final ValueBinder valueBinder;
private final ValueBinder<Object> valueBinder;
@SuppressWarnings({ "unchecked", "rawtypes" })
@SuppressWarnings({ "unchecked" })
public ValueConverterTypeAdapter(
String description,
BasicValueConverter<J, ?> converter,
JdbcTypeDescriptorIndicators indicators) {
super(
converter.getRelationalJavaDescriptor().getRecommendedJdbcType( indicators ),
(JavaType) converter.getRelationalJavaDescriptor()
(JavaType<J>) converter.getRelationalJavaDescriptor()
);
this.description = description;
this.converter = converter;
this.valueBinder = getJdbcTypeDescriptor().getBinder( converter.getRelationalJavaDescriptor() );
this.converter = (BasicValueConverter<J, Object>) converter;
this.valueBinder = getJdbcTypeDescriptor().getBinder( this.converter.getRelationalJavaDescriptor() );
}
@Override
@ -51,20 +49,18 @@ public class ValueConverterTypeAdapter<J> extends AbstractSingleColumnStandardBa
}
@Override
@SuppressWarnings({ "unchecked" })
public void nullSafeSet(
CallableStatement st,
Object value,
J value,
String name,
SharedSessionContractImplementor session) throws SQLException {
final Object converted = converter.toRelationalValue( (J) value );
final Object converted = converter.toRelationalValue( value );
valueBinder.bind( st, converted, name, session );
}
@Override
@SuppressWarnings({ "unchecked" })
protected void nullSafeSet(PreparedStatement st, Object value, int index, WrapperOptions options) throws SQLException {
final Object converted = converter.toRelationalValue( (J) value );
protected void nullSafeSet(PreparedStatement st, J value, int index, WrapperOptions options) throws SQLException {
final Object converted = converter.toRelationalValue( value );
valueBinder.bind( st, converted, index, options );
}

View File

@ -45,6 +45,7 @@ import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.type.BasicType;
import org.hibernate.type.BasicTypeRegistry;
import org.hibernate.type.CustomType;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.spi.JavaTypeDescriptorRegistry;
import org.hibernate.type.descriptor.jdbc.JdbcType;
@ -366,7 +367,7 @@ public class MetadataBuildingProcess {
final JavaType<?> jtd;
if ( type instanceof CustomType ) {
final CustomType customType = (CustomType) type;
final CustomType<Object> customType = (CustomType<Object>) type;
jtd = customType.getJavaTypeDescriptor();
}
else {
@ -389,7 +390,7 @@ public class MetadataBuildingProcess {
@Override
public void contributeType(UserType type, String[] keys) {
contributeType( new CustomType( type, keys, getTypeConfiguration() ) );
contributeType( new CustomType<Object>( type, keys, getTypeConfiguration() ) );
}
@Override
@ -422,14 +423,22 @@ public class MetadataBuildingProcess {
contributor.contribute( typeContributions, options.getServiceRegistry() );
}
// add fallback type descriptors
final JdbcTypeDescriptorRegistry jdbcTypeRegistry = bootstrapContext.getTypeConfiguration()
.getJdbcTypeDescriptorRegistry();
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.UUID, SqlTypes.BINARY );
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.JSON, SqlTypes.VARBINARY );
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.INET, SqlTypes.VARBINARY );
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.INTERVAL_SECOND, SqlTypes.NUMERIC );
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.GEOMETRY, SqlTypes.VARBINARY );
addFallbackIfNecessary( jdbcTypeRegistry, SqlTypes.POINT, SqlTypes.VARBINARY );
// add explicit application registered types
bootstrapContext.getTypeConfiguration()
.addBasicTypeRegistrationContributions( options.getBasicTypeRegistrations() );
// For NORMALIZE, we replace the standard types that use TIMESTAMP_WITH_TIMEZONE to use TIMESTAMP
if ( options.getDefaultTimeZoneStorage() == TimeZoneStorageStrategy.NORMALIZE ) {
final JdbcTypeDescriptorRegistry jdbcTypeRegistry = bootstrapContext.getTypeConfiguration()
.getJdbcTypeDescriptorRegistry();
final JavaTypeDescriptorRegistry javaTypeRegistry = bootstrapContext.getTypeConfiguration()
.getJavaTypeDescriptorRegistry();
final JdbcType timestampDescriptor = jdbcTypeRegistry.getDescriptor( Types.TIMESTAMP );
@ -458,4 +467,13 @@ public class MetadataBuildingProcess {
);
}
}
private static void addFallbackIfNecessary(
JdbcTypeDescriptorRegistry jdbcTypeRegistry,
int typeCode,
int fallbackTypeCode) {
if ( !jdbcTypeRegistry.hasRegisteredDescriptor( typeCode ) ) {
jdbcTypeRegistry.addDescriptor( typeCode, jdbcTypeRegistry.getDescriptor( fallbackTypeCode ) );
}
}
}

View File

@ -2519,8 +2519,9 @@ public class ModelBinder {
}
if ( typeInstance instanceof UserType ) {
return new CustomType(
(UserType) typeInstance,
//noinspection unchecked
return new CustomType<>(
(UserType<Object>) typeInstance,
bootstrapContext.getTypeConfiguration()
);
}

View File

@ -34,6 +34,9 @@ import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorBuilderImpl;
import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorBuilderImpl;
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
import org.hibernate.type.FormatMapper;
import org.hibernate.type.JacksonJsonFormatMapper;
import org.hibernate.type.JsonBJsonFormatMapper;
import org.jboss.logging.Logger;
@ -107,6 +110,7 @@ public class StrategySelectorBuilder {
addSqmMultiTableMutationStrategies( strategySelector );
addImplicitNamingStrategies( strategySelector );
addCacheKeysFactories( strategySelector );
addJsonFormatMappers( strategySelector );
// apply auto-discovered registrations
for ( StrategyRegistrationProvider provider : classLoaderService.loadJavaServices( StrategyRegistrationProvider.class ) ) {
@ -227,4 +231,17 @@ public class StrategySelectorBuilder {
SimpleCacheKeysFactory.class
);
}
private void addJsonFormatMappers(StrategySelectorImpl strategySelector) {
strategySelector.registerStrategyImplementor(
FormatMapper.class,
JacksonJsonFormatMapper.SHORT_NAME,
JacksonJsonFormatMapper.class
);
strategySelector.registerStrategyImplementor(
FormatMapper.class,
JsonBJsonFormatMapper.SHORT_NAME,
JsonBJsonFormatMapper.class
);
}
}

View File

@ -38,6 +38,7 @@ import org.hibernate.query.sqm.sql.SqmTranslatorFactory;
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
import org.hibernate.resource.jdbc.spi.StatementInspector;
import org.hibernate.tuple.entity.EntityTuplizerFactory;
import org.hibernate.type.FormatMapper;
/**
* Convenience base class for custom implementors of SessionFactoryOptions, using delegation
@ -474,4 +475,9 @@ public class AbstractDelegatingSessionFactoryOptions implements SessionFactoryOp
public TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy() {
return delegate.getDefaultTimeZoneStorageStrategy();
}
@Override
public FormatMapper getJsonFormatMapper() {
return delegate.getJsonFormatMapper();
}
}

View File

@ -15,23 +15,24 @@ import org.hibernate.usertype.UserType;
* @author Steve Ebersole
*/
public class BasicTypeRegistration {
private final BasicType basicType;
private final BasicType<?> basicType;
private final String[] registrationKeys;
public BasicTypeRegistration(BasicType basicType) {
public BasicTypeRegistration(BasicType<?> basicType) {
this( basicType, basicType.getRegistrationKeys() );
}
public BasicTypeRegistration(BasicType basicType, String[] registrationKeys) {
public BasicTypeRegistration(BasicType<?> basicType, String[] registrationKeys) {
this.basicType = basicType;
this.registrationKeys = registrationKeys;
}
public BasicTypeRegistration(UserType type, String[] keys, TypeConfiguration typeConfiguration) {
this( new CustomType( type, keys, typeConfiguration ), keys );
public BasicTypeRegistration(UserType<?> type, String[] keys, TypeConfiguration typeConfiguration) {
//noinspection unchecked
this( new CustomType<>( (UserType<Object>) type, keys, typeConfiguration ), keys );
}
public BasicType getBasicType() {
public BasicType<?> getBasicType() {
return basicType;
}

View File

@ -37,6 +37,7 @@ import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
import org.hibernate.resource.jdbc.spi.StatementInspector;
import org.hibernate.stat.Statistics;
import org.hibernate.tuple.entity.EntityTuplizerFactory;
import org.hibernate.type.FormatMapper;
/**
* Aggregator of special options used to build the SessionFactory.
@ -351,4 +352,6 @@ public interface SessionFactoryOptions extends QueryEngineOptions {
int getPreferredSqlTypeCodeForBoolean();
TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy();
FormatMapper getJsonFormatMapper();
}

View File

@ -2389,7 +2389,27 @@ public interface AvailableSettings {
*
* @since 6.0
*/
String PREFERRED_BOOLEAN_JDBC_TYPE_CODE = "hibernate.type.perferred_boolean_jdbc_type_code";
String PREFERRED_BOOLEAN_JDBC_TYPE_CODE = "hibernate.type.preferred_boolean_jdbc_type_code";
/**
* Names a {@link org.hibernate.type.FormatMapper} implementation to be applied to
* the {@link org.hibernate.SessionFactory} for JSON serialization and deserialization.
* Can reference<ul>
* <li>FormatMapper instance</li>
* <li>FormatMapper implementation {@link Class} reference</li>
* <li>FormatMapper implementation class name (FQN)</li>
* <li>one of the short hand constants<ul>
* <li>jackson</li>
* <li>jsonb</li>
* </ul>
* </li>
* </ul>
* By default the first of the possible providers that is available in the runtime is used,
* according to the listing order.
*
* @since 6.0
*/
String JSON_FORMAT_MAPPER = "hibernate.type.json_format_mapper";
/**
* Global setting for configuring the default storage for the time zone information for time zone based types.

View File

@ -38,6 +38,7 @@ import org.hibernate.mapping.Table;
import org.hibernate.procedure.internal.StandardCallableStatementSupport;
import org.hibernate.procedure.spi.CallableStatementSupport;
import org.hibernate.query.CastType;
import org.hibernate.query.IntervalType;
import org.hibernate.query.NullOrdering;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
@ -52,6 +53,7 @@ import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorHA
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.tool.schema.internal.StandardTableExporter;
import org.hibernate.tool.schema.spi.Exporter;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
@ -777,6 +779,9 @@ public abstract class AbstractHANADialect extends Dialect {
registerHibernateType( Types.BLOB, StandardBasicTypes.MATERIALIZED_BLOB.getName() );
registerHibernateType( Types.NVARCHAR, StandardBasicTypes.NSTRING.getName() );
registerColumnType( SqlTypes.GEOMETRY, "st_geometry" );
registerColumnType( SqlTypes.POINT, "st_point" );
registerHanaKeywords();
// createBlob() and createClob() are not supported by the HANA JDBC driver
@ -1597,7 +1602,7 @@ public abstract class AbstractHANADialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
switch (unit) {
case NANOSECOND:
case NATIVE:

View File

@ -6,22 +6,27 @@
*/
package org.hibernate.dialect;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.dialect.function.CommonFunctionFactory;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.OffsetFetchLimitHandler;
import org.hibernate.dialect.sequence.PostgreSQLSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.env.spi.IdentifierCaseStrategy;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
import org.hibernate.engine.jdbc.env.spi.NameQualifierSupport;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.IntervalType;
import org.hibernate.query.NullOrdering;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
import org.hibernate.sql.ast.spi.SqlAppender;
@ -30,7 +35,11 @@ import org.hibernate.sql.ast.tree.Statement;
import org.hibernate.sql.exec.spi.JdbcOperation;
import org.hibernate.type.BasicType;
import org.hibernate.type.BasicTypeRegistry;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.UUIDJdbcType;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
@ -62,19 +71,29 @@ public class CockroachDialect extends Dialect {
// * no support for java.sql.Clob
private final int version;
private final PostgreSQLDriverKind driverKind;
public CockroachDialect() {
this( 1920 );
}
public CockroachDialect(DialectResolutionInfo info) {
this( info.getDatabaseMajorVersion() * 100 + info.getDatabaseMinorVersion() * 10 );
this(
info.getDatabaseMajorVersion() * 100 + info.getDatabaseMinorVersion() * 10,
PostgreSQLDriverKind.determineKind( info )
);
}
public CockroachDialect(int version) {
// Assume PgJDBC by default
this( version, PostgreSQLDriverKind.PG_JDBC );
}
public CockroachDialect(int version, PostgreSQLDriverKind driverKind) {
super();
this.version = version;
this.driverKind = driverKind;
registerColumnType( Types.TINYINT, "smallint" ); //no tinyint
@ -94,10 +113,76 @@ public class CockroachDialect extends Dialect {
registerColumnType( Types.LONGNVARCHAR, "string" );
registerColumnType( Types.NCLOB, "string" );
registerColumnType( Types.JAVA_OBJECT, "json" );
registerColumnType( SqlTypes.UUID, "uuid" );
registerColumnType( SqlTypes.INTERVAL_SECOND, "interval second($s)" );
//register geometry type
registerColumnType( 5432, "geometry" );
// Prefer jsonb if possible
if ( getVersion() >= 2000 ) {
registerColumnType( SqlTypes.INET, "inet" );
registerColumnType( SqlTypes.JSON, "jsonb" );
}
else {
registerColumnType( SqlTypes.JSON, "json" );
}
registerColumnType( SqlTypes.GEOMETRY, "geometry" );
}
@Override
public String getTypeName(int code, Size size) throws HibernateException {
// The maximum scale for `interval second` is 6 unfortunately so we have to use numeric by default
switch ( code ) {
case SqlTypes.INTERVAL_SECOND:
final Integer scale = size.getScale();
if ( scale == null || scale > 6 ) {
return getTypeName( SqlTypes.NUMERIC, size );
}
}
return super.getTypeName( code, size );
}
@Override
public JdbcType resolveSqlTypeDescriptor(
String columnTypeName,
int jdbcTypeCode,
int precision,
int scale,
JdbcTypeDescriptorRegistry jdbcTypeDescriptorRegistry) {
if ( jdbcTypeCode == SqlTypes.OTHER ) {
switch ( columnTypeName ) {
case "uuid":
jdbcTypeCode = SqlTypes.UUID;
break;
case "json":
case "jsonb":
jdbcTypeCode = SqlTypes.JSON;
break;
case "inet":
jdbcTypeCode = SqlTypes.INET;
break;
}
}
return jdbcTypeDescriptorRegistry.getDescriptor( jdbcTypeCode );
}
@Override
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
super.contributeTypes( typeContributions, serviceRegistry );
final JdbcTypeDescriptorRegistry jdbcTypeRegistry = typeContributions.getTypeConfiguration()
.getJdbcTypeDescriptorRegistry();
if ( driverKind == PostgreSQLDriverKind.PG_JDBC ) {
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLIntervalSecondJdbcType.INSTANCE );
if ( getVersion() >= 2000 ) {
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLInetJdbcType.INSTANCE );
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLJsonbJdbcType.INSTANCE );
}
else {
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLJsonJdbcType.INSTANCE );
}
}
}
@Override
@ -373,7 +458,10 @@ public class CockroachDialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
if ( intervalType != null ) {
return "(?2+?3)";
}
switch ( unit ) {
case NANOSECOND:
return "(?3+(?2)/1e3*interval '1 microsecond')";

View File

@ -28,6 +28,7 @@ import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.query.IntervalType;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.mutation.internal.cte.CteStrategy;
@ -279,7 +280,7 @@ public class DB2Dialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
final StringBuilder pattern = new StringBuilder();
final boolean castTo;
if ( unit.isDateUnit() ) {

View File

@ -19,6 +19,7 @@ import org.hibernate.dialect.sequence.NoSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.IntervalType;
import org.hibernate.query.TemporalUnit;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
@ -90,7 +91,7 @@ public class DB2zDialect extends DB2Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
StringBuilder pattern = new StringBuilder();
final boolean castTo;
if ( unit.isDateUnit() ) {

View File

@ -35,6 +35,7 @@ import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.query.CastType;
import org.hibernate.query.IntervalType;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.sqm.mutation.internal.idtable.AfterUseAction;
@ -337,7 +338,7 @@ public class DerbyDialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
switch (unit) {
case NANOSECOND:
case NATIVE:

View File

@ -11,7 +11,9 @@ import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.dialect.sequence.NoSequenceSupport;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.FetchClauseType;
import org.hibernate.query.IntervalType;
import org.hibernate.query.NullOrdering;
import org.hibernate.ScrollMode;
import org.hibernate.boot.model.TypeContributions;
@ -75,6 +77,7 @@ import org.hibernate.tool.schema.internal.*;
import org.hibernate.tool.schema.spi.Exporter;
import org.hibernate.type.BasicType;
import org.hibernate.type.BasicTypeRegistry;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.Type;
import org.hibernate.type.descriptor.java.JavaType;
@ -91,6 +94,7 @@ import jakarta.persistence.TemporalType;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.*;
import java.time.Duration;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
@ -933,10 +937,11 @@ public abstract class Dialect implements ConversionContext {
* {@code timestampadd()} function call. The resulting
* pattern must contain ?1, ?2, and ?3 placeholders
* for the arguments.
* @param unit the first argument
* @param temporalType true if the third argument is a
* @param unit The unit to add to the temporal
* @param temporalType The type of the temporal
* @param intervalType The type of interval to add or null if it's not a native interval
*/
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
throw new NotYetImplementedFor6Exception();
}
@ -1033,7 +1038,7 @@ public abstract class Dialect implements ConversionContext {
}
public String getRawTypeName(JdbcType jdbcType) throws HibernateException {
return getRawTypeName( jdbcType.getJdbcTypeCode() );
return getRawTypeName( jdbcType.getDefaultSqlTypeCode() );
}
public String getTypeName(JdbcType jdbcType) throws HibernateException {
@ -1102,7 +1107,7 @@ public abstract class Dialect implements ConversionContext {
*
*/
public String getTypeName(JdbcType jdbcType, Size size) {
return getTypeName( jdbcType.getJdbcTypeCode(), size );
return getTypeName( jdbcType.getDefaultSqlTypeCode(), size );
}
/**
@ -1113,12 +1118,15 @@ public abstract class Dialect implements ConversionContext {
* @return The database type name
*/
public String getCastTypeName(SqlExpressable type, Long length, Integer precision, Integer scale) {
final JdbcMapping jdbcMapping = type.getJdbcMapping();
final JdbcType jdbcType = jdbcMapping.getJdbcTypeDescriptor();
final JavaType<?> javaType = jdbcMapping.getJavaTypeDescriptor();
Size size;
if ( length == null && precision == null ) {
//use defaults
size = getSizeStrategy().resolveSize(
type.getJdbcMapping().getJdbcTypeDescriptor(),
type.getJdbcMapping().getJavaTypeDescriptor(),
jdbcType,
javaType,
precision,
scale,
length
@ -1128,7 +1136,7 @@ public abstract class Dialect implements ConversionContext {
//use the given length/precision/scale
if ( precision != null && scale == null ) {
//needed for cast(x as BigInteger(p))
scale = type.getJdbcMapping().getJavaTypeDescriptor().getDefaultSqlScale();
scale = javaType.getDefaultSqlScale( Dialect.this, jdbcType );
}
size = new Size()
.setLength( length )
@ -1136,7 +1144,7 @@ public abstract class Dialect implements ConversionContext {
.setScale( scale );
}
return getTypeName( type.getJdbcMapping().getJdbcTypeDescriptor(), size );
return getTypeName( jdbcType, size );
}
/**
@ -3442,7 +3450,7 @@ public abstract class Dialect implements ConversionContext {
Integer scale,
Long length) {
final Size size = new Size();
int jdbcTypeCode = jdbcType.getJdbcTypeCode();
int jdbcTypeCode = jdbcType.getDefaultSqlTypeCode();
switch (jdbcTypeCode) {
case Types.BIT:
@ -3493,18 +3501,21 @@ public abstract class Dialect implements ConversionContext {
}
case Types.TIMESTAMP:
case Types.TIMESTAMP_WITH_TIMEZONE:
size.setPrecision( javaType.getDefaultSqlPrecision( Dialect.this ) );
size.setPrecision( javaType.getDefaultSqlPrecision( Dialect.this, jdbcType ) );
break;
case Types.NUMERIC:
case Types.DECIMAL:
size.setPrecision( javaType.getDefaultSqlPrecision( Dialect.this ) );
size.setScale( javaType.getDefaultSqlScale() );
size.setPrecision( javaType.getDefaultSqlPrecision( Dialect.this, jdbcType ) );
size.setScale( javaType.getDefaultSqlScale( Dialect.this, jdbcType ) );
break;
case Types.CLOB:
case Types.BLOB:
size.setLength( javaType.getDefaultSqlLength( Dialect.this, jdbcType ) );
break;
case SqlTypes.INTERVAL_SECOND:
size.setPrecision( javaType.getDefaultSqlPrecision( Dialect.this, jdbcType ) );
size.setScale( javaType.getDefaultSqlScale( Dialect.this, jdbcType ) );
break;
}
if ( precision != null ) {
@ -3718,6 +3729,14 @@ public abstract class Dialect implements ConversionContext {
}
}
public void appendIntervalLiteral(SqlAppender appender, Duration literal) {
appender.appendSql( "interval '" );
appender.appendSql( literal.getSeconds() );
appender.appendSql( '.' );
appender.appendSql( literal.getNano() );
appender.appendSql( '\'' );
}
/**
* Whether the Dialect supports timezone offset in temporal literals.
*/

View File

@ -4,60 +4,67 @@
* 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.test.id.usertype.inet;
package org.hibernate.dialect;
import java.lang.reflect.InvocationTargetException;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.time.Duration;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.BasicBinder;
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
import org.hibernate.type.descriptor.jdbc.JdbcType;
/**
* @author Vlad Mihalcea
* @author Christian Beikov
*/
public class InetJdbcType implements JdbcType {
public class DurationIntervalSecondJdbcType implements JdbcType {
public static final InetJdbcType INSTANCE = new InetJdbcType();
public static final DurationIntervalSecondJdbcType INSTANCE = new DurationIntervalSecondJdbcType();
@Override
public int getJdbcTypeCode() {
return Types.OTHER;
}
@Override
public int getDefaultSqlTypeCode() {
return SqlTypes.INTERVAL_SECOND;
}
@Override
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaTypeDescriptor) {
return (appender, value, dialect, wrapperOptions) -> dialect.appendIntervalLiteral(
appender,
javaTypeDescriptor.unwrap(
value,
Duration.class,
wrapperOptions
)
);
}
@Override
public <X> ValueBinder<X> getBinder(JavaType<X> javaTypeDescriptor) {
return new BasicBinder<X>( javaTypeDescriptor, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
try {
String stringValue = javaTypeDescriptor.unwrap( value, String.class, options );
Class clazz= ReflectHelper.classForName( "org.postgresql.util.PGobject", this.getClass());
Object holder = clazz.newInstance();
ReflectHelper.setterMethodOrNull( clazz, "type", String.class ).invoke( holder, "inet" );
ReflectHelper.setterMethodOrNull( clazz, "value", String.class ).invoke( holder, stringValue );
st.setObject( index, holder );
}
catch (ClassNotFoundException|IllegalAccessException|InstantiationException|InvocationTargetException e) {
throw new IllegalArgumentException( e );
}
st.setObject( index, javaTypeDescriptor.unwrap( value, Duration.class, options ) );
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
throw new UnsupportedOperationException();
st.setObject( name, javaTypeDescriptor.unwrap( value, Duration.class, options ) );
}
};
}
@ -67,18 +74,18 @@ public class InetJdbcType implements JdbcType {
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
@Override
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
return javaTypeDescriptor.wrap( rs.getString( paramIndex ), options );
return javaTypeDescriptor.wrap( rs.getObject( paramIndex, Duration.class ), options );
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
return javaTypeDescriptor.wrap( statement.getString( index ), options );
return javaTypeDescriptor.wrap( statement.getObject( index, Duration.class ), options );
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
throws SQLException {
return javaTypeDescriptor.wrap( statement.getString( name ), options );
return javaTypeDescriptor.wrap( statement.getObject( name, Duration.class ), options );
}
};
}

View File

@ -10,7 +10,9 @@ import java.sql.Types;
import jakarta.persistence.TemporalType;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.query.FetchClauseType;
import org.hibernate.query.IntervalType;
import org.hibernate.query.NullOrdering;
import org.hibernate.PessimisticLockException;
import org.hibernate.boot.TempTableDdlTransactionHandling;
@ -41,6 +43,7 @@ import org.hibernate.query.sqm.mutation.internal.idtable.AfterUseAction;
import org.hibernate.query.sqm.mutation.internal.idtable.IdTable;
import org.hibernate.query.sqm.mutation.internal.idtable.LocalTemporaryTableStrategy;
import org.hibernate.query.sqm.mutation.spi.SqmMultiTableMutationStrategy;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.SqlAstTranslatorFactory;
@ -52,6 +55,9 @@ import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorH2
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorLegacyImpl;
import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorNoOpImpl;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.jdbc.UUIDJdbcType;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
import org.jboss.logging.Logger;
@ -128,6 +134,20 @@ public class H2Dialect extends Dialect {
// which caused problems for schema update tool
registerColumnType( Types.NUMERIC, "decimal($p,$s)" );
}
registerColumnType( SqlTypes.UUID, "uuid" );
registerColumnType( SqlTypes.INTERVAL_SECOND, "interval second($p,$s)" );
registerColumnType( SqlTypes.GEOMETRY, "geometry" );
}
@Override
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
super.contributeTypes( typeContributions, serviceRegistry );
final JdbcTypeDescriptorRegistry jdbcTypeRegistry = typeContributions.getTypeConfiguration()
.getJdbcTypeDescriptorRegistry();
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
jdbcTypeRegistry.addDescriptorIfAbsent( DurationIntervalSecondJdbcType.INSTANCE );
}
private static int parseBuildId(DialectResolutionInfo info) {
@ -255,9 +275,11 @@ public class H2Dialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
if ( intervalType != null ) {
return "(?2+?3)";
}
return "dateadd(?1,?2,?3)";
}
@Override

View File

@ -13,6 +13,7 @@ import jakarta.persistence.TemporalType;
import org.hibernate.JDBCException;
import org.hibernate.LockMode;
import org.hibernate.query.IntervalType;
import org.hibernate.query.NullOrdering;
import org.hibernate.StaleObjectStateException;
import org.hibernate.boot.TempTableDdlTransactionHandling;
@ -279,7 +280,7 @@ public class HSQLDialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
StringBuilder pattern = new StringBuilder();
boolean castTo = temporalType != TemporalType.TIMESTAMP && !unit.isDateUnit();
switch (unit) {

View File

@ -13,7 +13,9 @@ import org.hibernate.engine.jdbc.env.spi.IdentifierCaseStrategy;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelperBuilder;
import org.hibernate.engine.jdbc.env.spi.NameQualifierSupport;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.query.CastType;
import org.hibernate.query.IntervalType;
import org.hibernate.query.NullOrdering;
import org.hibernate.PessimisticLockException;
import org.hibernate.boot.TempTableDdlTransactionHandling;
@ -55,9 +57,11 @@ import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.Statement;
import org.hibernate.sql.exec.spi.JdbcOperation;
import org.hibernate.type.NullType;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.JsonJdbcType;
import org.hibernate.type.descriptor.jdbc.NullJdbcType;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
@ -179,8 +183,9 @@ public class MySQLDialect extends Dialect {
if ( getMySQLVersion() >= 570) {
// MySQL 5.7 brings JSON native support with a dedicated datatype
// https://dev.mysql.com/doc/refman/5.7/en/json.html
registerColumnType(Types.JAVA_OBJECT, "json");
registerColumnType( SqlTypes.JSON, "json");
}
registerColumnType( SqlTypes.GEOMETRY, "geometry" );
registerKeyword( "key" );
@ -400,6 +405,13 @@ public class MySQLDialect extends Dialect {
public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
super.contributeTypes( typeContributions, serviceRegistry );
final JdbcTypeDescriptorRegistry jdbcTypeRegistry = typeContributions.getTypeConfiguration()
.getJdbcTypeDescriptorRegistry();
if ( getMySQLVersion() >= 570) {
jdbcTypeRegistry.addDescriptorIfAbsent( SqlTypes.JSON, JsonJdbcType.INSTANCE );
}
// MySQL requires a custom binder for binding untyped nulls with the NULL type
typeContributions.contributeJdbcTypeDescriptor( NullJdbcType.INSTANCE );
@ -512,7 +524,7 @@ public class MySQLDialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
switch (unit) {
case NANOSECOND:
return "timestampadd(microsecond,(?2)/1e3,?3)";
@ -704,7 +716,10 @@ public class MySQLDialect extends Dialect {
@Override
public String getCastTypeName(SqlExpressable type, Long length, Integer precision, Integer scale) {
switch ( type.getJdbcMapping().getJdbcTypeDescriptor().getJdbcTypeCode() ) {
final JdbcMapping jdbcMapping = type.getJdbcMapping();
final JdbcType jdbcType = jdbcMapping.getJdbcTypeDescriptor();
final JavaType<?> javaType = jdbcMapping.getJavaTypeDescriptor();
switch ( jdbcType.getDefaultSqlTypeCode() ) {
case Types.INTEGER:
case Types.BIGINT:
case Types.SMALLINT:
@ -722,8 +737,8 @@ public class MySQLDialect extends Dialect {
//the default scale is 0 (no decimal places)
return String.format(
"decimal(%d, %d)",
precision == null ? type.getJdbcMapping().getJavaTypeDescriptor().getDefaultSqlPrecision(this) : precision,
scale == null ? type.getJdbcMapping().getJavaTypeDescriptor().getDefaultSqlScale() : scale
precision == null ? javaType.getDefaultSqlPrecision( this, jdbcType ) : precision,
scale == null ? javaType.getDefaultSqlScale( this, jdbcType ) : scale
);
case Types.VARBINARY:
case Types.LONGVARBINARY:
@ -732,9 +747,9 @@ public class MySQLDialect extends Dialect {
//inconsistent with other Dialects which need a length
return String.format(
"binary(%d)",
length != null ? length : type.getJdbcMapping().getJavaTypeDescriptor().getDefaultSqlLength(
length != null ? length : javaType.getDefaultSqlLength(
this,
type.getJdbcMapping().getJdbcTypeDescriptor()
jdbcType
)
);
case Types.VARCHAR:
@ -744,9 +759,9 @@ public class MySQLDialect extends Dialect {
//inconsistent with other Dialects which need a length
return String.format(
"char(%d)",
length != null ? length : type.getJdbcMapping().getJavaTypeDescriptor().getDefaultSqlLength(
length != null ? length : javaType.getDefaultSqlLength(
this,
type.getJdbcMapping().getJdbcTypeDescriptor()
jdbcType
)
);
default:

View File

@ -37,6 +37,7 @@ import org.hibernate.procedure.internal.StandardCallableStatementSupport;
import org.hibernate.procedure.spi.CallableStatementSupport;
import org.hibernate.query.CastType;
import org.hibernate.query.FetchClauseType;
import org.hibernate.query.IntervalType;
import org.hibernate.query.SemanticException;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
@ -58,6 +59,7 @@ import org.hibernate.tool.schema.extract.internal.SequenceInformationExtractorOr
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
import org.hibernate.type.JavaObjectType;
import org.hibernate.type.NullType;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.BlobJdbcType;
@ -121,6 +123,7 @@ public class OracleDialect extends Dialect {
registerNumericTypeMappings();
registerDateTimeTypeMappings();
registerBinaryTypeMappings();
registerExtendedTypeMappings();
registerReverseHibernateTypeMappings();
registerDefaultProperties();
@ -371,7 +374,7 @@ public class OracleDialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
StringBuilder pattern = new StringBuilder();
pattern.append("(?3+");
switch ( unit ) {
@ -579,6 +582,12 @@ public class OracleDialect extends Dialect {
registerColumnType( Types.VARBINARY, "blob" );
}
protected void registerExtendedTypeMappings() {
if ( getVersion() >= 1000 ) {
registerColumnType( SqlTypes.GEOMETRY, "MDSYS.SDO_GEOMETRY" );
}
}
protected void registerReverseHibernateTypeMappings() {
}

View File

@ -21,6 +21,7 @@ import java.util.TimeZone;
import jakarta.persistence.TemporalType;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.LockOptions;
import org.hibernate.PessimisticLockException;
@ -35,6 +36,7 @@ import org.hibernate.dialect.pagination.LimitOffsetLimitHandler;
import org.hibernate.dialect.pagination.OffsetFetchLimitHandler;
import org.hibernate.dialect.sequence.PostgreSQLSequenceSupport;
import org.hibernate.dialect.sequence.SequenceSupport;
import org.hibernate.engine.jdbc.Size;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
import org.hibernate.engine.jdbc.env.spi.IdentifierCaseStrategy;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
@ -51,6 +53,7 @@ import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
import org.hibernate.procedure.internal.PostgresCallableStatementSupport;
import org.hibernate.procedure.spi.CallableStatementSupport;
import org.hibernate.query.FetchClauseType;
import org.hibernate.query.IntervalType;
import org.hibernate.query.SemanticException;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
@ -64,12 +67,14 @@ import org.hibernate.sql.ast.spi.StandardSqlAstTranslatorFactory;
import org.hibernate.sql.ast.tree.Statement;
import org.hibernate.sql.exec.spi.JdbcOperation;
import org.hibernate.type.JavaObjectType;
import org.hibernate.type.PostgresUUIDType;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.BlobJdbcType;
import org.hibernate.type.descriptor.jdbc.ClobJdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.ObjectNullAsBinaryTypeJdbcType;
import org.hibernate.type.descriptor.jdbc.UUIDJdbcType;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
import static org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor.extractUsingTemplate;
@ -88,9 +93,13 @@ public class PostgreSQLDialect extends Dialect {
private static final PostgreSQLIdentityColumnSupport IDENTITY_COLUMN_SUPPORT = new PostgreSQLIdentityColumnSupport();
private final int version;
private final PostgreSQLDriverKind driverKind;
public PostgreSQLDialect(DialectResolutionInfo info) {
this( info.getDatabaseMajorVersion() * 100 + info.getDatabaseMinorVersion() * 10 );
this(
info.getDatabaseMajorVersion() * 100 + info.getDatabaseMinorVersion() * 10,
PostgreSQLDriverKind.determineKind( info )
);
}
public PostgreSQLDialect() {
@ -98,8 +107,14 @@ public class PostgreSQLDialect extends Dialect {
}
public PostgreSQLDialect(int version) {
// Assume PgJDBC by default
this( version, PostgreSQLDriverKind.PG_JDBC );
}
public PostgreSQLDialect(int version, PostgreSQLDriverKind driverKind) {
super();
this.version = version;
this.driverKind = driverKind;
registerColumnType( Types.TINYINT, "smallint" ); //no tinyint, not even in Postgres 11
@ -121,20 +136,66 @@ public class PostgreSQLDialect extends Dialect {
registerColumnType( Types.LONGVARCHAR, "text" );
registerColumnType( Types.LONGNVARCHAR, "text" );
registerColumnType( 5432, "geometry" );
registerColumnType( SqlTypes.INET, "inet" );
registerColumnType( SqlTypes.INTERVAL_SECOND, "interval second($s)" );
if ( getVersion() >= 820 ) {
registerColumnType( PostgresUUIDType.INSTANCE.getJdbcTypeDescriptor().getDefaultSqlTypeCode(), "uuid" );
registerColumnType( SqlTypes.UUID, "uuid" );
if ( getVersion() >= 920 ) {
registerColumnType( Types.JAVA_OBJECT, "json" );
// Prefer jsonb if possible
if ( getVersion() >= 940 ) {
registerColumnType( SqlTypes.JSON, "jsonb" );
}
else {
registerColumnType( SqlTypes.JSON, "json" );
}
}
}
registerColumnType( SqlTypes.GEOMETRY, "geometry" );
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, DEFAULT_BATCH_SIZE );
getDefaultProperties().setProperty( Environment.NON_CONTEXTUAL_LOB_CREATION, "true" );
}
@Override
public String getTypeName(int code, Size size) throws HibernateException {
// The maximum scale for `interval second` is 6 unfortunately so we have to use numeric by default
switch ( code ) {
case SqlTypes.INTERVAL_SECOND:
final Integer scale = size.getScale();
if ( scale == null || scale > 6 ) {
return getTypeName( SqlTypes.NUMERIC, size );
}
}
return super.getTypeName( code, size );
}
@Override
public JdbcType resolveSqlTypeDescriptor(
String columnTypeName,
int jdbcTypeCode,
int precision,
int scale,
JdbcTypeDescriptorRegistry jdbcTypeDescriptorRegistry) {
if ( jdbcTypeCode == SqlTypes.OTHER ) {
switch ( columnTypeName ) {
case "uuid":
jdbcTypeCode = SqlTypes.UUID;
break;
case "json":
case "jsonb":
jdbcTypeCode = SqlTypes.JSON;
break;
case "inet":
jdbcTypeCode = SqlTypes.INET;
break;
}
}
return jdbcTypeDescriptorRegistry.getDescriptor( jdbcTypeCode );
}
@Override
public int getVersion() {
return version;
@ -185,7 +246,10 @@ public class PostgreSQLDialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
if ( intervalType != null ) {
return "(?2+?3)";
}
switch ( unit ) {
case NANOSECOND:
return "(?3+(?2)/1e3*interval '1 microsecond')";
@ -937,9 +1001,17 @@ public class PostgreSQLDialect extends Dialect {
jdbcTypeRegistry.addDescriptor( Types.BLOB, BlobJdbcType.BLOB_BINDING );
jdbcTypeRegistry.addDescriptor( Types.CLOB, ClobJdbcType.CLOB_BINDING );
if ( getVersion() >= 820 ) {
// HHH-9562
typeContributions.contributeType( PostgresUUIDType.INSTANCE );
if ( driverKind == PostgreSQLDriverKind.PG_JDBC ) {
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLInetJdbcType.INSTANCE );
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLIntervalSecondJdbcType.INSTANCE );
if ( getVersion() >= 820 ) {
// HHH-9562
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
if ( getVersion() >= 920 ) {
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLJsonbJdbcType.INSTANCE );
}
}
}
// PostgreSQL requires a custom binder for binding untyped nulls as VARBINARY

View File

@ -0,0 +1,31 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* 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.dialect;
import org.hibernate.engine.jdbc.dialect.spi.DialectResolutionInfo;
/**
*
* @author Christian Beikov
*/
public enum PostgreSQLDriverKind {
PG_JDBC,
OTHER;
public static PostgreSQLDriverKind determineKind(DialectResolutionInfo dialectResolutionInfo) {
final String driverName = dialectResolutionInfo.getDriverName();
// By default we assume PgJDBC
if ( driverName == null ) {
return PG_JDBC;
}
switch ( driverName ) {
case "PostgreSQL JDBC Driver":
return PG_JDBC;
}
return OTHER;
}
}

View File

@ -0,0 +1,42 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* 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.dialect;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType;
/**
* @author Christian Beikov
*/
public class PostgreSQLInetJdbcType extends PostgreSQLPGObjectJdbcType {
public static final PostgreSQLInetJdbcType INSTANCE = new PostgreSQLInetJdbcType();
public PostgreSQLInetJdbcType() {
super( "inet", SqlTypes.INET );
}
@Override
protected <X> X fromString(String string, JavaType<X> javaTypeDescriptor, WrapperOptions options) {
final String host;
if ( string == null ) {
host = null;
}
else {
// The default toString representation of the inet type adds the subnet mask
final int slashIndex = string.lastIndexOf( '/' );
if ( slashIndex == -1 ) {
host = string;
}
else {
host = string.substring( 0, slashIndex );
}
}
return javaTypeDescriptor.wrap( host, options );
}
}

View File

@ -0,0 +1,157 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* 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.dialect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.time.Duration;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.AdjustableJdbcType;
import org.hibernate.type.descriptor.jdbc.BasicBinder;
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.JdbcTypeDescriptorIndicators;
/**
* @author Christian Beikov
*/
public class PostgreSQLIntervalSecondJdbcType implements AdjustableJdbcType {
public static final PostgreSQLIntervalSecondJdbcType INSTANCE = new PostgreSQLIntervalSecondJdbcType();
private static final Constructor<Object> PG_INTERVAL_CONSTRUCTOR;
static {
Constructor<Object> constructor;
try {
final Class<?> pgIntervalClass = ReflectHelper.classForName(
"org.postgresql.util.PGInterval",
PostgreSQLIntervalSecondJdbcType.class
);
constructor = (Constructor<Object>) pgIntervalClass.getConstructor(
int.class,
int.class,
int.class,
int.class,
int.class,
double.class
);
}
catch (Exception e) {
throw new RuntimeException( "Could not initialize PostgreSQLPGObjectJdbcType", e );
}
PG_INTERVAL_CONSTRUCTOR = constructor;
}
@Override
public int getJdbcTypeCode() {
return Types.OTHER;
}
@Override
public int getDefaultSqlTypeCode() {
return SqlTypes.INTERVAL_SECOND;
}
@Override
public JdbcType resolveIndicatedType(JdbcTypeDescriptorIndicators indicators, JavaType<?> domainJtd) {
// The default scale is 9
if ( indicators.getColumnScale() == JdbcTypeDescriptorIndicators.NO_COLUMN_SCALE || indicators.getColumnScale() > 6 ) {
return indicators.getTypeConfiguration().getJdbcTypeDescriptorRegistry().getDescriptor( SqlTypes.NUMERIC );
}
return this;
}
@Override
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaTypeDescriptor) {
return (appender, value, dialect, wrapperOptions) -> dialect.appendIntervalLiteral(
appender,
javaTypeDescriptor.unwrap(
value,
Duration.class,
wrapperOptions
)
);
}
@Override
public <X> ValueBinder<X> getBinder(JavaType<X> javaTypeDescriptor) {
return new BasicBinder<X>( javaTypeDescriptor, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
final Duration duration = getJavaTypeDescriptor().unwrap( value, Duration.class, options );
st.setObject( index, constructInterval( duration ) );
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
final Duration duration = getJavaTypeDescriptor().unwrap( value, Duration.class, options );
st.setObject( name, constructInterval( duration ) );
}
private Object constructInterval(Duration d) {
long secondsLong = d.getSeconds();
long minutesLong = secondsLong / 60;
long hoursLong = minutesLong / 60;
long daysLong = hoursLong / 24;
int days = Math.toIntExact( daysLong );
int hours = (int) ( hoursLong - daysLong * 24 );
int minutes = (int) ( minutesLong - hoursLong * 60 );
double seconds = ( (double) ( secondsLong - minutesLong * 60 ) )
+ ( (double) d.getNano() ) / 1_000_000_000d;
try {
return PG_INTERVAL_CONSTRUCTOR.newInstance(
0,// years
0, // months
days,
hours,
minutes,
seconds
);
}
catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
throw new IllegalArgumentException( e );
}
}
};
}
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaTypeDescriptor) {
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
@Override
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
return getJavaTypeDescriptor().wrap( rs.getString( paramIndex ), options );
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
return getJavaTypeDescriptor().wrap( statement.getString( index ), options );
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
throws SQLException {
return getJavaTypeDescriptor().wrap( statement.getString( name ), options );
}
};
}
}

View File

@ -0,0 +1,41 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* 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.dialect;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType;
/**
* @author Christian Beikov
*/
public class PostgreSQLJsonJdbcType extends PostgreSQLPGObjectJdbcType {
public static final PostgreSQLJsonJdbcType INSTANCE = new PostgreSQLJsonJdbcType();
public PostgreSQLJsonJdbcType() {
super( "json", SqlTypes.JSON );
}
@Override
protected <X> X fromString(String string, JavaType<X> javaTypeDescriptor, WrapperOptions options) {
return options.getSessionFactory().getFastSessionServices().getJsonFormatMapper().fromString(
string,
javaTypeDescriptor,
options
);
}
@Override
protected <X> String toString(X value, JavaType<X> javaTypeDescriptor, WrapperOptions options) {
return options.getSessionFactory().getFastSessionServices().getJsonFormatMapper().toString(
value,
javaTypeDescriptor,
options
);
}
}

View File

@ -0,0 +1,41 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* 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.dialect;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType;
/**
* @author Christian Beikov
*/
public class PostgreSQLJsonbJdbcType extends PostgreSQLPGObjectJdbcType {
public static final PostgreSQLJsonbJdbcType INSTANCE = new PostgreSQLJsonbJdbcType();
public PostgreSQLJsonbJdbcType() {
super( "jsonb", SqlTypes.JSON );
}
@Override
protected <X> X fromString(String string, JavaType<X> javaTypeDescriptor, WrapperOptions options) {
return options.getSessionFactory().getFastSessionServices().getJsonFormatMapper().fromString(
string,
javaTypeDescriptor,
options
);
}
@Override
protected <X> String toString(X value, JavaType<X> javaTypeDescriptor, WrapperOptions options) {
return options.getSessionFactory().getFastSessionServices().getJsonFormatMapper().toString(
value,
javaTypeDescriptor,
options
);
}
}

View File

@ -0,0 +1,159 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* 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.dialect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.jdbc.BasicBinder;
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
import org.hibernate.type.descriptor.jdbc.JdbcType;
/**
* @author Christian Beikov
*/
public abstract class PostgreSQLPGObjectJdbcType implements JdbcType {
private static final Constructor<Object> PG_OBJECT_CONSTRUCTOR;
private static final Method TYPE_SETTER;
private static final Method VALUE_SETTER;
static {
Constructor<Object> constructor;
Method typeSetter;
Method valueSetter;
try {
final Class<?> pgObjectClass = ReflectHelper.classForName(
"org.postgresql.util.PGobject",
PostgreSQLPGObjectJdbcType.class
);
//noinspection unchecked
constructor = (Constructor<Object>) pgObjectClass.getConstructor();
typeSetter = ReflectHelper.setterMethodOrNull( pgObjectClass, "type", String.class );
valueSetter = ReflectHelper.setterMethodOrNull( pgObjectClass, "value", String.class );
}
catch (Exception e) {
throw new RuntimeException( "Could not initialize PostgreSQLPGObjectJdbcType", e );
}
PG_OBJECT_CONSTRUCTOR = constructor;
TYPE_SETTER = typeSetter;
VALUE_SETTER = valueSetter;
}
private final String typeName;
private final int sqlTypeCode;
public PostgreSQLPGObjectJdbcType(String typeName, int sqlTypeCode) {
this.typeName = typeName;
this.sqlTypeCode = sqlTypeCode;
}
@Override
public int getJdbcTypeCode() {
return Types.OTHER;
}
@Override
public int getDefaultSqlTypeCode() {
return sqlTypeCode;
}
protected <X> X fromString(String string, JavaType<X> javaTypeDescriptor, WrapperOptions options) {
return javaTypeDescriptor.wrap( string, options );
}
protected <X> String toString(X value, JavaType<X> javaTypeDescriptor, WrapperOptions options) {
return javaTypeDescriptor.unwrap( value, String.class, options );
}
@Override
public <X> ValueBinder<X> getBinder(JavaType<X> javaTypeDescriptor) {
return new BasicBinder<X>( javaTypeDescriptor, this ) {
@Override
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
throws SQLException {
final String stringValue = ( (PostgreSQLPGObjectJdbcType) getJdbcTypeDescriptor() ).toString(
value,
getJavaTypeDescriptor(),
options
);
try {
Object holder = PG_OBJECT_CONSTRUCTOR.newInstance();
TYPE_SETTER.invoke( holder, typeName );
VALUE_SETTER.invoke( holder, stringValue );
st.setObject( index, holder );
}
catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
throw new IllegalArgumentException( e );
}
}
@Override
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
throws SQLException {
final String stringValue = ( (PostgreSQLPGObjectJdbcType) getJdbcTypeDescriptor() ).toString(
value,
getJavaTypeDescriptor(),
options
);
try {
Object holder = PG_OBJECT_CONSTRUCTOR.newInstance();
TYPE_SETTER.invoke( holder, typeName );
VALUE_SETTER.invoke( holder, stringValue );
st.setObject( name, holder );
}
catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
throw new IllegalArgumentException( e );
}
}
};
}
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaTypeDescriptor) {
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
@Override
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
return ( (PostgreSQLPGObjectJdbcType) getJdbcTypeDescriptor() ).fromString(
rs.getString( paramIndex ),
getJavaTypeDescriptor(),
options
);
}
@Override
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
return ( (PostgreSQLPGObjectJdbcType) getJdbcTypeDescriptor() ).fromString(
statement.getString( index ),
getJavaTypeDescriptor(),
options
);
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
throws SQLException {
return ( (PostgreSQLPGObjectJdbcType) getJdbcTypeDescriptor() ).fromString(
statement.getString( name ),
getJavaTypeDescriptor(),
options
);
}
};
}
}

View File

@ -34,6 +34,7 @@ import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.query.CastType;
import org.hibernate.query.FetchClauseType;
import org.hibernate.query.IntervalType;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.service.ServiceRegistry;
@ -48,6 +49,7 @@ import org.hibernate.tool.schema.internal.StandardSequenceExporter;
import org.hibernate.tool.schema.spi.Exporter;
import org.hibernate.type.BasicType;
import org.hibernate.type.BasicTypeRegistry;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.SmallIntJdbcType;
@ -102,6 +104,7 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
registerColumnType( Types.TIME, "time" );
registerColumnType( Types.TIMESTAMP, "datetime2($p)" );
registerColumnType( Types.TIMESTAMP_WITH_TIMEZONE, "datetimeoffset($p)" );
registerColumnType( SqlTypes.GEOMETRY, "geometry" );
}
if ( getVersion() >= 11 ) {
@ -607,7 +610,7 @@ public class SQLServerDialect extends AbstractTransactSQLDialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
// dateadd() supports only especially small magnitudes
// since it casts its argument to int (and unfortunately
// there's no dateadd_big()) so here we need to use two

View File

@ -29,6 +29,7 @@ import org.hibernate.mapping.Table;
import org.hibernate.mapping.UniqueKey;
import org.hibernate.metamodel.mapping.SqlExpressable;
import org.hibernate.persister.entity.Lockable;
import org.hibernate.query.IntervalType;
import org.hibernate.query.SemanticException;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.spi.QueryEngine;
@ -448,7 +449,7 @@ public class SpannerDialect extends Dialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
if ( temporalType == TemporalType.TIMESTAMP ) {
switch (unit) {
case YEAR:

View File

@ -27,6 +27,7 @@ import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.exception.spi.TemplatedViolatedConstraintNameExtractor;
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
import org.hibernate.internal.util.JdbcExceptionHelper;
import org.hibernate.query.IntervalType;
import org.hibernate.query.TemporalUnit;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.sql.ForUpdateFragment;
@ -229,7 +230,7 @@ public class SybaseASEDialect extends SybaseDialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
//TODO!!
switch ( unit ) {
case NANOSECOND:

View File

@ -18,6 +18,7 @@ import org.hibernate.engine.jdbc.env.spi.NameQualifierSupport;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.CastType;
import org.hibernate.query.IntervalType;
import org.hibernate.query.TemporalUnit;
import org.hibernate.query.TrimSpec;
import org.hibernate.query.spi.QueryEngine;
@ -272,7 +273,7 @@ public class SybaseDialect extends AbstractTransactSQLDialect {
}
@Override
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType) {
public String timestampaddPattern(TemporalUnit unit, TemporalType temporalType, IntervalType intervalType) {
//TODO!!
return "dateadd(?1,?2,?3)";
}

View File

@ -97,7 +97,10 @@ public class TimestampaddFunction
final String pattern = dialect.timestampaddPattern(
unit,
TypeConfiguration.getSqlTemporalType( to.getExpressionType() )
TypeConfiguration.getSqlTemporalType( to.getExpressionType() ),
TypeConfiguration.getSqlIntervalType(
( (Expression) arguments.get( 1 ) ).getExpressionType().getJdbcMappings().get( 0 )
)
);
final PatternRenderer renderer = new PatternRenderer( pattern );
@ -182,7 +185,9 @@ public class TimestampaddFunction
getName(),
this::render,
asList( sqlAstArguments ),
impliedResultType,
impliedResultType != null
? impliedResultType
: (AllowableFunctionReturnType<?>) to.getExpressionType().getJdbcMappings().get( 0 ),
to.getExpressionType()
);
}

View File

@ -99,7 +99,9 @@ public class TimestampdiffFunction
getName(),
this::render,
asList( sqlAstArguments ),
impliedResultType,
impliedResultType != null
? impliedResultType
: (AllowableFunctionReturnType<?>) field.getExpressionType().getJdbcMapping(),
field.getExpressionType()
);
}

View File

@ -22,6 +22,11 @@ public abstract class AbstractDelegatingWrapperOptions implements WrapperOptions
*/
protected abstract SessionImplementor delegate();
@Override
public SessionFactoryImplementor getSessionFactory() {
return delegate().getSessionFactory();
}
@Override
public boolean useStreamForLobBinding() {
return delegate().useStreamForLobBinding();

View File

@ -80,6 +80,11 @@ public interface SharedSessionContractImplementor
*/
SessionFactoryImplementor getFactory();
@Override
default SessionFactoryImplementor getSessionFactory() {
return getFactory();
}
@Override
default TypeConfiguration getTypeConfiguration() {
return getFactory().getTypeConfiguration();

View File

@ -99,7 +99,7 @@ public final class IdentifierGeneratorHelper {
return ( (ResultSetIdentifierConsumer) type ).consumeIdentifier( rs );
}
if ( CustomType.class.isInstance( type ) ) {
final CustomType customType = (CustomType) type;
final CustomType<Object> customType = (CustomType<Object>) type;
if ( ResultSetIdentifierConsumer.class.isInstance( customType.getUserType() ) ) {
return ( (ResultSetIdentifierConsumer) customType.getUserType() ).consumeIdentifier( rs );
}

View File

@ -67,6 +67,7 @@ import org.hibernate.jpa.internal.util.ConfigurationHelper;
import org.hibernate.jpa.internal.util.LockOptionsHelper;
import org.hibernate.resource.transaction.spi.TransactionCoordinatorBuilder;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.type.FormatMapper;
import static org.hibernate.cfg.AvailableSettings.JAKARTA_LOCK_SCOPE;
import static org.hibernate.cfg.AvailableSettings.JAKARTA_LOCK_TIMEOUT;
@ -166,6 +167,7 @@ public final class FastSessionServices {
private final CacheStoreMode defaultCacheStoreMode;
private final CacheRetrieveMode defaultCacheRetrieveMode;
private final ConnectionObserverStatsBridge defaultJdbcObservers;
private final FormatMapper jsonFormatMapper;
FastSessionServices(SessionFactoryImpl sf) {
Objects.requireNonNull( sf );
@ -238,7 +240,7 @@ public final class FastSessionServices {
this.defaultSessionEventListeners = sessionFactoryOptions.getBaselineSessionEventsListenerBuilder();
this.defaultLockOptions = initializeDefaultLockOptions( defaultSessionProperties );
this.initialSessionFlushMode = initializeDefaultFlushMode( defaultSessionProperties );
this.jsonFormatMapper = sessionFactoryOptions.getJsonFormatMapper();
}
private static FlushMode initializeDefaultFlushMode(Map<String, Object> defaultSessionProperties) {
@ -367,4 +369,8 @@ public final class FastSessionServices {
public TimeZoneStorageStrategy getDefaultTimeZoneStorageStrategy() {
return defaultTimeZoneStorageStrategy;
}
public FormatMapper getJsonFormatMapper() {
return jsonFormatMapper;
}
}

View File

@ -1,25 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* 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.jpa;
import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.type.Type;
/**
* Can be used to bind query parameter values. Allows to provide additional details about the
* parameter value/binding.
*
* @author Steve Ebersole
*
* @deprecated (since 6.0) use {@link org.hibernate.query.TypedParameterValue} instead.
*/
@Deprecated
public class TypedParameterValue extends org.hibernate.query.TypedParameterValue {
public TypedParameterValue(Type type, Object value) {
super( (AllowableParameterType) type, value );
}
}

View File

@ -187,6 +187,30 @@ public class BasicValue extends SimpleValue implements JdbcTypeDescriptorIndicat
}
}
@Override
public int getColumnPrecision() {
final Selectable column = getColumn();
if ( column != null && column instanceof Column ) {
final Integer length = ( (Column) column ).getPrecision();
return length == null ? NO_COLUMN_PRECISION : length;
}
else {
return NO_COLUMN_PRECISION;
}
}
@Override
public int getColumnScale() {
final Selectable column = getColumn();
if ( column != null && column instanceof Column ) {
final Integer length = ( (Column) column ).getScale();
return length == null ? NO_COLUMN_SCALE : length;
}
else {
return NO_COLUMN_SCALE;
}
}
@Override
public void addColumn(Column incomingColumn) {
super.addColumn( incomingColumn );
@ -724,7 +748,7 @@ public class BasicValue extends SimpleValue implements JdbcTypeDescriptorIndicat
// envers - grr
setTypeParameters( properties );
final CustomType customType = new CustomType( typeInstance, typeConfiguration );
final CustomType<Object> customType = new CustomType<>( (UserType<Object>) typeInstance, typeConfiguration );
this.resolution = new UserTypeResolution( customType, null, properties );
}
}

View File

@ -681,7 +681,7 @@ public abstract class SimpleValue implements KeyValue {
}
}
);
int jdbcTypeCode = recommendedJdbcType.getJdbcTypeCode();
int jdbcTypeCode = recommendedJdbcType.getDefaultSqlTypeCode();
if ( isLob() ) {
if ( LobTypeMappings.isMappedToKnownLobCode( jdbcTypeCode ) ) {
jdbcTypeCode = LobTypeMappings.getLobCodeTypeMapping( jdbcTypeCode );

View File

@ -72,6 +72,10 @@ public class NamedEnumValueConverter<E extends Enum<E>> implements EnumValueConv
return jdbcType.getJdbcTypeCode();
}
public int getDefaultSqlTypeCode() {
return jdbcType.getDefaultSqlTypeCode();
}
@Override
public String toSqlLiteral(Object value) {
//noinspection rawtypes

View File

@ -30,6 +30,11 @@ public class SessionFactoryBasedWrapperOptions implements WrapperOptions {
throw new UnsupportedOperationException();
}
@Override
public SessionFactoryImplementor getSessionFactory() {
return factory;
}
@Override
public boolean useStreamForLobBinding() {
return factory.getFastSessionServices().useStreamForLobBinding();

View File

@ -407,7 +407,7 @@ public class ProcedureCallImpl<R>
final ProcedureParameterImpl<T> procedureParameter = new ProcedureParameterImpl<>(
position,
mode,
parameterType.getJavaType(),
parameterType == null ? javaType : parameterType.getJavaType(),
parameterType
);
registerParameter( procedureParameter );
@ -805,10 +805,9 @@ public class ProcedureCallImpl<R>
}
@Override
@SuppressWarnings("unchecked")
protected List<R> doList() {
if ( getMaxResults() == 0 ) {
return Collections.EMPTY_LIST;
return Collections.emptyList();
}
try {
final Output rtn = outputs().getCurrent();
@ -816,6 +815,7 @@ public class ProcedureCallImpl<R>
throw new IllegalStateException( "Current CallableStatement ou was not a ResultSet, but getResultList was called" );
}
//noinspection unchecked
return ( (ResultSetOutput) rtn ).getResultList();
}
catch (NoMoreOutputsException e) {
@ -834,7 +834,7 @@ public class ProcedureCallImpl<R>
}
@Override
public ScrollableResultsImplementor scroll(ScrollMode scrollMode) {
public ScrollableResultsImplementor<R> scroll(ScrollMode scrollMode) {
throw new UnsupportedOperationException( "Query#scroll is not valid for ProcedureCall/StoredProcedureQuery" );
}
@ -948,75 +948,82 @@ public class ProcedureCallImpl<R>
@Override
public <P> ProcedureCallImplementor<R> setParameter(QueryParameter<P> parameter, P value) {
return (ProcedureCallImplementor<R>) super.setParameter( parameter, value );
super.setParameter( parameter, value );
return this;
}
@Override
public <P> ProcedureCallImplementor<R> setParameter(Parameter<P> parameter, P value) {
return (ProcedureCallImplementor<R>) super.setParameter( parameter, value );
super.setParameter( parameter, value );
return this;
}
@Override
public ProcedureCallImplementor<R> setParameter(String name, Object value) {
return (ProcedureCallImplementor<R>) super.setParameter( name, value );
super.setParameter( name, value );
return this;
}
@Override
public ProcedureCallImplementor<R> setParameter(int position, Object value) {
return (ProcedureCallImplementor<R>) super.setParameter( position, value );
super.setParameter( position, value );
return this;
}
@Override
public <P> ProcedureCallImplementor<R> setParameter(
QueryParameter<P> parameter,
P value,
AllowableParameterType type) {
AllowableParameterType<P> type) {
super.setParameter( parameter, value, type );
return this;
}
// @Override
// public <P> ProcedureCallImplementor<R> setParameter(QueryParameter<P> parameter, P value, Type type) {
// return (ProcedureCallImplementor<R>) super.setParameter( parameter, value, type );
// super.setParameter( parameter, value, type );
// return this;
// }
@Override
public ProcedureCallImplementor<R> setParameter(String name, Object value, AllowableParameterType type) {
public <P> ProcedureCallImplementor<R> setParameter(String name, P value, AllowableParameterType<P> type) {
super.setParameter( name, value, type );
return this;
}
// @Override
// public ProcedureCallImplementor<R> setParameter(String name, Object value, Type type) {
// return (ProcedureCallImplementor<R>) super.setParameter( name, value, type );
// super.setParameter( name, value, type );
// return this;
// }
@Override
public ProcedureCallImplementor<R> setParameter(int position, Object value, AllowableParameterType type) {
public <P> ProcedureCallImplementor<R> setParameter(int position, P value, AllowableParameterType<P> type) {
super.setParameter( position, value, type );
return this;
}
@Override
public ProcedureCallImplementor<R> setParameter(String name, Object value, BasicTypeReference<?> type) {
public <P> ProcedureCallImplementor<R> setParameter(String name, P value, BasicTypeReference<P> type) {
super.setParameter( name, value, type );
return this;
}
@Override
public ProcedureCallImplementor<R> setParameter(int position, Object value, BasicTypeReference<?> type) {
public <P> ProcedureCallImplementor<R> setParameter(int position, P value, BasicTypeReference<P> type) {
super.setParameter( position, value, type );
return this;
}
@Override
public <P> ProcedureCallImplementor<R> setParameter(QueryParameter<P> parameter, P val, BasicTypeReference<?> type) {
public <P> ProcedureCallImplementor<R> setParameter(QueryParameter<P> parameter, P val, BasicTypeReference<P> type) {
super.setParameter( parameter, val, type );
return this;
}
// @Override
// public ProcedureCallImplementor<R> setParameter(int position, Object value, Type type) {
// return (ProcedureCallImplementor<R>) super.setParameter( position, value, type );
// super.setParameter( position, value, type );
// return this;
// }
@Override
@ -1024,52 +1031,59 @@ public class ProcedureCallImpl<R>
QueryParameter<P> parameter,
P value,
TemporalType temporalPrecision) {
return (ProcedureCallImplementor<R>) super.setParameter( parameter, value, temporalPrecision );
super.setParameter( parameter, value, temporalPrecision );
return this;
}
@Override
public ProcedureCallImplementor<R> setParameter(String name, Object value, TemporalType temporalPrecision) {
return (ProcedureCallImplementor<R>) super.setParameter( name, value, temporalPrecision );
super.setParameter( name, value, temporalPrecision );
return this;
}
@Override
public ProcedureCallImplementor<R> setParameter(int position, Object value, TemporalType temporalPrecision) {
return (ProcedureCallImplementor<R>) super.setParameter( position, value, temporalPrecision );
super.setParameter( position, value, temporalPrecision );
return this;
}
@Override
public ProcedureCallImplementor<R> setParameter(
Parameter parameter,
Parameter<Calendar> parameter,
Calendar value,
TemporalType temporalPrecision) {
//noinspection unchecked
return (ProcedureCallImplementor<R>) super.setParameter( parameter, value, temporalPrecision );
super.setParameter( parameter, value, temporalPrecision );
return this;
}
@Override
public ProcedureCallImplementor<R> setParameter(Parameter parameter, Date value, TemporalType temporalPrecision) {
//noinspection unchecked
return (ProcedureCallImplementor<R>) super.setParameter( parameter, value, temporalPrecision );
public ProcedureCallImplementor<R> setParameter(Parameter<Date> parameter, Date value, TemporalType temporalPrecision) {
super.setParameter( parameter, value, temporalPrecision );
return this;
}
@Override
public ProcedureCallImplementor<R> setParameter(String name, Calendar value, TemporalType temporalPrecision) {
return (ProcedureCallImplementor<R>) super.setParameter( name, value, temporalPrecision );
super.setParameter( name, value, temporalPrecision );
return this;
}
@Override
public ProcedureCallImplementor<R> setParameter(String name, Date value, TemporalType temporalPrecision) {
return (ProcedureCallImplementor<R>) super.setParameter( name, value, temporalPrecision );
super.setParameter( name, value, temporalPrecision );
return this;
}
@Override
public ProcedureCallImplementor<R> setParameter(int position, Calendar value, TemporalType temporalPrecision) {
return (ProcedureCallImplementor<R>) super.setParameter( position, value, temporalPrecision );
super.setParameter( position, value, temporalPrecision );
return this;
}
@Override
public ProcedureCallImplementor<R> setParameter(int position, Date value, TemporalType temporalPrecision) {
return (ProcedureCallImplementor<R>) super.setParameter( position, value, temporalPrecision );
super.setParameter( position, value, temporalPrecision );
return this;
}
@Override

View File

@ -49,24 +49,24 @@ public class ProcedureParamBindings implements QueryParameterBindings {
@Override
public <P> ProcedureParameterBinding<P> getBinding(QueryParameterImplementor<P> parameter) {
return getQueryParamerBinding( (ProcedureParameterImplementor) parameter );
return getQueryParamerBinding( (ProcedureParameterImplementor<P>) parameter );
}
public <P> ProcedureParameterBinding<P> getQueryParamerBinding(ProcedureParameterImplementor<P> parameter) {
final ProcedureParameterImplementor procParam = parameterMetadata.resolve( parameter );
ProcedureParameterBindingImplementor binding = bindingMap.get( procParam );
final ProcedureParameterImplementor<P> procParam = parameterMetadata.resolve( parameter );
ProcedureParameterBindingImplementor<?> binding = bindingMap.get( procParam );
if ( binding == null ) {
if ( !parameterMetadata.containsReference( parameter ) ) {
throw new IllegalArgumentException( "Passed parameter is not registered with this query" );
}
//noinspection unchecked
binding = new ProcedureParameterBindingImpl( procParam, typeResolver );
binding = new ProcedureParameterBindingImpl<>( procParam, typeResolver );
bindingMap.put( procParam, binding );
}
return binding;
//noinspection unchecked
return (ProcedureParameterBinding<P>) binding;
}
@Override

View File

@ -91,8 +91,7 @@ public class ProcedureParameterImpl<T> extends AbstractQueryParameter<T> impleme
public NamedCallableQueryMemento.ParameterMemento toMemento() {
return session -> {
if ( getName() != null ) {
//noinspection unchecked
return new ProcedureParameterImpl(
return new ProcedureParameterImpl<>(
getName(),
getMode(),
javaType,
@ -100,8 +99,7 @@ public class ProcedureParameterImpl<T> extends AbstractQueryParameter<T> impleme
);
}
else {
//noinspection unchecked
return new ProcedureParameterImpl(
return new ProcedureParameterImpl<>(
getPosition(),
getMode(),
javaType,
@ -135,7 +133,7 @@ public class ProcedureParameterImpl<T> extends AbstractQueryParameter<T> impleme
CallableStatement statement,
int startIndex,
ProcedureCallImplementor<?> procedureCall) throws SQLException {
final QueryParameterBinding<?> binding = procedureCall.getParameterBindings().getBinding( this );
final QueryParameterBinding<T> binding = procedureCall.getParameterBindings().getBinding( this );
final TypeConfiguration typeConfiguration = procedureCall.getSession().getFactory().getTypeConfiguration();
final AllowableParameterType<T> typeToUse = BindingTypeHelper.INSTANCE.resolveTemporalPrecision(
binding == null || binding.getExplicitTemporalPrecision() == null
@ -186,10 +184,10 @@ public class ProcedureParameterImpl<T> extends AbstractQueryParameter<T> impleme
}
if ( mode == ParameterMode.INOUT || mode == ParameterMode.IN ) {
final ValueBinder binder;
final BasicType basicType;
final ValueBinder<T> binder;
final BasicType<T> basicType;
if ( typeToUse instanceof BasicType ) {
basicType = ( (BasicType) typeToUse );
basicType = ( (BasicType<T>) typeToUse );
binder = basicType.getJdbcValueBinder();
}
else {
@ -211,7 +209,8 @@ public class ProcedureParameterImpl<T> extends AbstractQueryParameter<T> impleme
);
if ( procedureCall.getParameterStrategy() == ParameterStrategy.NAMED
&& canDoNameParameterBinding( typeToUse, procedureCall ) ) {
( (ProcedureParameterNamedBinder) typeToUse ).nullSafeSet(
//noinspection unchecked
( (ProcedureParameterNamedBinder<T>) typeToUse ).nullSafeSet(
statement,
null,
this.getName(),
@ -237,7 +236,8 @@ public class ProcedureParameterImpl<T> extends AbstractQueryParameter<T> impleme
else {
if ( procedureCall.getParameterStrategy() == ParameterStrategy.NAMED
&& canDoNameParameterBinding( typeToUse, procedureCall ) ) {
( (ProcedureParameterNamedBinder) typeToUse ).nullSafeSet(
//noinspection unchecked
( (ProcedureParameterNamedBinder<T>) typeToUse ).nullSafeSet(
statement,
binding.getBindValue(),
this.getName(),
@ -255,7 +255,7 @@ public class ProcedureParameterImpl<T> extends AbstractQueryParameter<T> impleme
}
private boolean canDoNameParameterBinding(
AllowableParameterType hibernateType,
AllowableParameterType<?> hibernateType,
ProcedureCallImplementor<?> procedureCall) {
final ExtractedDatabaseMetaData databaseMetaData = procedureCall.getSession()
.getJdbcCoordinator()
@ -265,7 +265,7 @@ public class ProcedureParameterImpl<T> extends AbstractQueryParameter<T> impleme
.getExtractedDatabaseMetaData();
return
databaseMetaData.supportsNamedParameters()
&& ProcedureParameterNamedBinder.class.isInstance( hibernateType )
&& ( (ProcedureParameterNamedBinder) hibernateType ).canDoSetting();
&& hibernateType instanceof ProcedureParameterNamedBinder
&& ( (ProcedureParameterNamedBinder<?>) hibernateType ).canDoSetting();
}
}

View File

@ -162,11 +162,12 @@ public class ProcedureParameterMetadataImpl implements ProcedureParameterMetadat
}
@Override
public ProcedureParameterImplementor<?> resolve(Parameter param) {
public <P> ProcedureParameterImplementor<P> resolve(Parameter<P> param) {
if ( param instanceof ProcedureParameterImplementor ) {
for ( ProcedureParameterImplementor p : parameters ) {
for ( ProcedureParameterImplementor<?> p : parameters ) {
if ( p == param ) {
return p;
//noinspection unchecked
return (ProcedureParameterImplementor<P>) p;
}
}
}

View File

@ -0,0 +1,19 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* 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.query;
/**
* The different types of intervals that SQL defines.
*
* @author Christian Beikov
*/
public enum IntervalType {
/**
* A second based interval.
**/
SECOND;
}

View File

@ -42,7 +42,7 @@ import org.hibernate.type.BasicTypeReference;
* </li>
* <li>
* Tables used via {@link #addSynchronizedQuerySpace}, {@link #addSynchronizedEntityName} and
* {@link #addSynchronizedEntityClass}. This allows Hibernate to know how to properly deal with
* {@link SynchronizeableQuery#addSynchronizedEntityClass}. This allows Hibernate to know how to properly deal with
* auto-flush checking as well as cached query results if the results of the query are being
* cached.
* </li>
@ -106,7 +106,7 @@ public interface NativeQuery<T> extends Query<T>, SynchronizeableQuery {
*
* @return {@code this}, for method chaining
*/
NativeQuery<T> addScalar(String columnAlias, BasicDomainType type);
NativeQuery<T> addScalar(String columnAlias, BasicDomainType<?> type);
/**
* Declare a scalar query result using the specified result type.
@ -281,7 +281,7 @@ public interface NativeQuery<T> extends Query<T>, SynchronizeableQuery {
*
* @return {@code this}, for method chaining
*/
NativeQuery<T> addEntity(Class entityType);
NativeQuery<T> addEntity(Class<?> entityType);
/**
* Declare a "root" entity.
@ -291,7 +291,7 @@ public interface NativeQuery<T> extends Query<T>, SynchronizeableQuery {
*
* @return {@code this}, for method chaining
*/
NativeQuery<T> addEntity(String tableAlias, Class entityType);
NativeQuery<T> addEntity(String tableAlias, Class<?> entityType);
/**
* Declare a "root" entity, specifying a lock mode.
@ -302,7 +302,7 @@ public interface NativeQuery<T> extends Query<T>, SynchronizeableQuery {
*
* @return {@code this}, for method chaining
*/
NativeQuery<T> addEntity(String tableAlias, Class entityClass, LockMode lockMode);
NativeQuery<T> addEntity(String tableAlias, Class<?> entityClass, LockMode lockMode);
/**
* Declare a join fetch result.
@ -507,7 +507,7 @@ public interface NativeQuery<T> extends Query<T>, SynchronizeableQuery {
NativeQuery<T> addSynchronizedEntityName(String entityName) throws MappingException;
@Override
NativeQuery<T> addSynchronizedEntityClass(Class entityClass) throws MappingException;
NativeQuery<T> addSynchronizedEntityClass(Class<?> entityClass) throws MappingException;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -664,7 +664,7 @@ public interface NativeQuery<T> extends Query<T>, SynchronizeableQuery {
<P> NativeQuery<T> setParameterList(QueryParameter<P> parameter, Collection<P> values);
@Override
NativeQuery<T> setParameterList(String name, Collection values);
NativeQuery<T> setParameterList(String name, Collection<?> values);
// @Override
// default NativeQuery<T> setParameterList(String name, Collection values, Type type) {
@ -672,55 +672,55 @@ public interface NativeQuery<T> extends Query<T>, SynchronizeableQuery {
// }
@Override
NativeQuery<T> setParameterList(String name, Collection values, AllowableParameterType type);
<P> NativeQuery<T> setParameterList(String name, Collection<? extends P> values, AllowableParameterType<P> type);
// @Override
// NativeQuery<T> setParameterList(String name, Object[] values, Type type);
@Override
NativeQuery<T> setParameterList(String name, Object[] values, AllowableParameterType type);
NativeQuery<T> setParameterList(String name, Object[] values, AllowableParameterType<?> type);
@Override
NativeQuery<T> setParameterList(String name, Object[] values);
@Override
NativeQuery<T> setParameter(String name, Object val, AllowableParameterType type);
<P> NativeQuery<T> setParameter(String name, P val, AllowableParameterType<P> type);
@Override
NativeQuery<T> setParameter(int position, Object val, AllowableParameterType type);
<P> NativeQuery<T> setParameter(int position, P val, AllowableParameterType<P> type);
@Override
<P> NativeQuery<T> setParameter(QueryParameter<P> parameter, P val, AllowableParameterType type);
<P> NativeQuery<T> setParameter(QueryParameter<P> parameter, P val, AllowableParameterType<P> type);
@Override
NativeQuery<T> setParameter(String name, Object val, BasicTypeReference<?> type);
<P> NativeQuery<T> setParameter(String name, P val, BasicTypeReference<P> type);
@Override
NativeQuery<T> setParameter(int position, Object val, BasicTypeReference<?> type);
<P> NativeQuery<T> setParameter(int position, P val, BasicTypeReference<P> type);
@Override
<P> NativeQuery<T> setParameter(QueryParameter<P> parameter, P val, BasicTypeReference<?> type);
<P> NativeQuery<T> setParameter(QueryParameter<P> parameter, P val, BasicTypeReference<P> type);
@Override
NativeQuery<T> setParameterList(int position, Collection values);
NativeQuery<T> setParameterList(int position, Collection<?> values);
@Override
NativeQuery<T> setParameterList(String name, Collection values, Class type);
<P> NativeQuery<T> setParameterList(String name, Collection<? extends P> values, Class<P> type);
@Override
NativeQuery<T> setParameterList(int position, Collection values, Class type);
<P> NativeQuery<T> setParameterList(int position, Collection<? extends P> values, Class<P> type);
// @Override
// NativeQuery<T> setParameterList(int position, Collection values, Type type);
@Override
NativeQuery<T> setParameterList(int position, Collection values, AllowableParameterType type);
<P> NativeQuery<T> setParameterList(int position, Collection<? extends P> values, AllowableParameterType<P> type);
// @Override
// NativeQuery<T> setParameterList(int position, Object[] values, Type type);
@Override
NativeQuery<T> setParameterList(int position, Object[] values, AllowableParameterType type);
NativeQuery<T> setParameterList(int position, Object[] values, AllowableParameterType<?> type);
@Override
NativeQuery<T> setParameterList(int position, Object[] values);

View File

@ -56,7 +56,7 @@ public interface ParameterMetadata {
* According to the spec, only Parameter references obtained from the provider
* are valid.
*/
QueryParameter<?> resolve(Parameter param);
<P> QueryParameter<P> resolve(Parameter<P> param);
default <T> AllowableParameterType<T> getInferredParameterType(QueryParameter<T> parameter) {
return null;

View File

@ -288,7 +288,7 @@ public interface Query<R> extends TypedQuery<R>, CommonQueryContract {
*
* @return {@code this}, for method chaining
*/
Query<R> setParameter(String name, Object val, AllowableParameterType type);
<P> Query<R> setParameter(String name, P val, AllowableParameterType<P> type);
/**
* Bind a value to a JDBC-style query parameter.
@ -300,7 +300,7 @@ public interface Query<R> extends TypedQuery<R>, CommonQueryContract {
*
* @return {@code this}, for method chaining
*/
Query<R> setParameter(int position, Object val, AllowableParameterType type);
<P> Query<R> setParameter(int position, P val, AllowableParameterType<P> type);
/**
* Bind a named query parameter using the supplied Type
@ -311,7 +311,7 @@ public interface Query<R> extends TypedQuery<R>, CommonQueryContract {
*
* @return {@code this}, for method chaining
*/
Query<R> setParameter(String name, Object val, BasicTypeReference<?> type);
<P> Query<R> setParameter(String name, P val, BasicTypeReference<P> type);
/**
* Bind a value to a JDBC-style query parameter.
@ -323,7 +323,7 @@ public interface Query<R> extends TypedQuery<R>, CommonQueryContract {
*
* @return {@code this}, for method chaining
*/
Query<R> setParameter(int position, Object val, BasicTypeReference<?> type);
<P> Query<R> setParameter(int position, P val, BasicTypeReference<P> type);
/**
* Bind a named query parameter as some form of date/time using
@ -371,7 +371,7 @@ public interface Query<R> extends TypedQuery<R>, CommonQueryContract {
*
* @return {@code this}, for method chaining
*/
<P> Query<R> setParameter(QueryParameter<P> parameter, P val, AllowableParameterType type);
<P> Query<R> setParameter(QueryParameter<P> parameter, P val, AllowableParameterType<P> type);
/**
* Bind a query parameter using the supplied Type
@ -382,7 +382,7 @@ public interface Query<R> extends TypedQuery<R>, CommonQueryContract {
*
* @return {@code this}, for method chaining
*/
<P> Query<R> setParameter(QueryParameter<P> parameter, P val, BasicTypeReference<?> type);
<P> Query<R> setParameter(QueryParameter<P> parameter, P val, BasicTypeReference<P> type);
Query<R> setParameter(Parameter<Instant> param, Instant value, TemporalType temporalType);
@ -537,7 +537,7 @@ public interface Query<R> extends TypedQuery<R>, CommonQueryContract {
*
* @return {@code this}, for method chaining
*/
Query<R> setParameterList(String name, Collection values);
Query<R> setParameterList(String name, Collection<?> values);
/**
* Bind multiple values to a positional query parameter. The Hibernate type of the parameter is
@ -550,7 +550,7 @@ public interface Query<R> extends TypedQuery<R>, CommonQueryContract {
*
* @return {@code this}, for method chaining
*/
Query<R> setParameterList(int position, Collection values);
Query<R> setParameterList(int position, Collection<?> values);
/**
* Bind multiple values to a named query parameter. The Hibernate type of the parameter is
@ -563,7 +563,7 @@ public interface Query<R> extends TypedQuery<R>, CommonQueryContract {
*
* @return {@code this}, for method chaining
*/
Query<R> setParameterList(String name, Collection values, Class type);
<P> Query<R> setParameterList(String name, Collection<? extends P> values, Class<P> type);
/**
* Bind multiple values to a positional query parameter. The Hibernate type of the parameter is
@ -576,7 +576,7 @@ public interface Query<R> extends TypedQuery<R>, CommonQueryContract {
*
* @return {@code this}, for method chaining
*/
Query<R> setParameterList(int position, Collection values, Class type);
<P> Query<R> setParameterList(int position, Collection<? extends P> values, Class<P> type);
// /**
// * Bind multiple values to a named query parameter. This is useful for binding
@ -622,7 +622,7 @@ public interface Query<R> extends TypedQuery<R>, CommonQueryContract {
*
* @return {@code this}, for method chaining
*/
Query<R> setParameterList(String name, Collection values, AllowableParameterType type);
<P> Query<R> setParameterList(String name, Collection<? extends P> values, AllowableParameterType<P> type);
/**
* Bind multiple values to a positional query parameter. This is useful for binding
@ -634,7 +634,7 @@ public interface Query<R> extends TypedQuery<R>, CommonQueryContract {
*
* @return {@code this}, for method chaining
*/
Query<R> setParameterList(int position, Collection values, AllowableParameterType type);
<P> Query<R> setParameterList(int position, Collection<? extends P> values, AllowableParameterType<P> type);
// /**
// * Bind multiple values to a named query parameter. This is useful for binding
@ -680,7 +680,7 @@ public interface Query<R> extends TypedQuery<R>, CommonQueryContract {
*
* @return {@code this}, for method chaining
*/
Query<R> setParameterList(String name, Object[] values, AllowableParameterType type);
Query<R> setParameterList(String name, Object[] values, AllowableParameterType<?> type);
/**
* Bind multiple values to a named query parameter. This is useful for binding
@ -692,7 +692,7 @@ public interface Query<R> extends TypedQuery<R>, CommonQueryContract {
*
* @return {@code this}, for method chaining
*/
Query<R> setParameterList(int position, Object[] values, AllowableParameterType type);
Query<R> setParameterList(int position, Object[] values, AllowableParameterType<?> type);
/**
* Bind multiple values to a named query parameter. The Hibernate type of the parameter is

View File

@ -61,5 +61,5 @@ public interface SynchronizeableQuery {
*
* @throws MappingException Indicates the given class could not be resolved as an entity
*/
SynchronizeableQuery addSynchronizedEntityClass(Class entityClass) throws MappingException;
SynchronizeableQuery addSynchronizedEntityClass(Class<?> entityClass) throws MappingException;
}

View File

@ -8,6 +8,7 @@ package org.hibernate.query;
import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.type.BasicTypeReference;
/**
* Can be used to bind query parameter values. Allows to provide additional details about the
@ -15,11 +16,17 @@ import org.hibernate.metamodel.model.domain.AllowableParameterType;
*
* @author Steve Ebersole
*/
public class TypedParameterValue {
private final AllowableParameterType type;
private final Object value;
public final class TypedParameterValue<J> {
public TypedParameterValue(AllowableParameterType type, Object value) {
private final Object type;
private final J value;
public TypedParameterValue(AllowableParameterType<J> type, J value) {
this.type = type;
this.value = value;
}
public TypedParameterValue(BasicTypeReference<J> type, J value) {
this.type = type;
this.value = value;
}
@ -29,7 +36,7 @@ public class TypedParameterValue {
*
* @return The value to be bound
*/
public Object getValue() {
public J getValue() {
return value;
}
@ -38,7 +45,16 @@ public class TypedParameterValue {
*
* @return The Hibernate type to use.
*/
public AllowableParameterType getType() {
return type;
public AllowableParameterType<J> getType() {
return type instanceof AllowableParameterType ? (AllowableParameterType<J>) type : null;
}
/**
* The specific Hibernate type reference to use to bind the value.
*
* @return The Hibernate type reference to use.
*/
public BasicTypeReference<J> getTypeReference() {
return type instanceof BasicTypeReference ? (BasicTypeReference<J>) type : null;
}
}

View File

@ -21,7 +21,6 @@ import jakarta.persistence.Parameter;
import org.hibernate.QueryException;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.internal.util.collections.IdentitySet;
import org.hibernate.internal.util.compare.ComparableComparator;
import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.query.QueryParameter;
@ -210,9 +209,9 @@ public class ParameterMetadataImpl implements ParameterMetadataImplementor {
}
@Override
public QueryParameterImplementor<?> resolve(Parameter param) {
public <P> QueryParameterImplementor<P> resolve(Parameter<P> param) {
if ( param instanceof QueryParameterImplementor ) {
return (QueryParameterImplementor) param;
return (QueryParameterImplementor<P>) param;
}
throw new IllegalArgumentException( "Could not resolve jakarta.persistence.Parameter to org.hibernate.query.QueryParameter" );

View File

@ -250,14 +250,15 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T>, J
}
@Override
public void setBindValues(Collection<T> values) {
public void setBindValues(Collection<? extends T> values) {
this.isBound = true;
this.isMultiValued = true;
this.bindValue = null;
this.bindValues = values;
//noinspection unchecked
this.bindValues = (Collection<T>) values;
final Iterator<T> iterator = values.iterator();
final Iterator<? extends T> iterator = values.iterator();
T value = null;
while ( value == null && iterator.hasNext() ) {
value = iterator.next();
@ -265,13 +266,13 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T>, J
if ( bindType == null && value != null ) {
//noinspection unchecked
this.bindType = (AllowableParameterType) typeResolver.resolveParameterBindType( value );
this.bindType = (AllowableParameterType<T>) typeResolver.resolveParameterBindType( value );
}
}
@Override
public void setBindValues(Collection<T> values, AllowableParameterType<T> clarifiedType) {
public void setBindValues(Collection<? extends T> values, AllowableParameterType<T> clarifiedType) {
if ( clarifiedType != null ) {
this.bindType = clarifiedType;
}
@ -280,7 +281,7 @@ public class QueryParameterBindingImpl<T> implements QueryParameterBinding<T>, J
@Override
public void setBindValues(
Collection<T> values,
Collection<? extends T> values,
TemporalType temporalTypePrecision,
TypeConfiguration typeConfiguration) {
setBindValues( values );

View File

@ -92,7 +92,7 @@ public class ResultMementoBasicStandard implements ResultMementoBasic {
else if ( UserType.class.isAssignableFrom( registeredJtd.getJavaTypeClass() ) ) {
final ManagedBean<UserType<?>> userTypeBean = (ManagedBean) beanRegistry.getBean( registeredJtd.getJavaTypeClass() );
// todo (6.0) : is this the best approach? or should we keep a Class<? extends UserType> -> CustomType mapping somewhere?
resolvedBasicType = new CustomType( userTypeBean.getBeanInstance(), sessionFactory.getTypeConfiguration() );
resolvedBasicType = new CustomType<>( (UserType<Object>) userTypeBean.getBeanInstance(), sessionFactory.getTypeConfiguration() );
this.explicitJavaTypeDescriptor = resolvedBasicType.getJavaTypeDescriptor();
}
else {

View File

@ -55,7 +55,6 @@ import org.hibernate.property.access.spi.BuiltInPropertyAccessStrategies;
import org.hibernate.property.access.spi.Getter;
import org.hibernate.property.access.spi.PropertyAccess;
import org.hibernate.query.IllegalQueryOperationException;
import org.hibernate.query.Query;
import org.hibernate.query.QueryLogging;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.ResultListTransformer;
@ -954,7 +953,15 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override
public <P> QueryImplementor<R> setParameter(Parameter<P> parameter, P value) {
if ( value instanceof TypedParameterValue ) {
setParameter( parameter, ( (TypedParameterValue) value ).getValue(), ( (TypedParameterValue) value ).getType() );
@SuppressWarnings("unchecked")
final TypedParameterValue<P> typedValue = (TypedParameterValue<P>) value;
final AllowableParameterType<P> type = typedValue.getType();
if ( type != null ) {
setParameter( parameter, typedValue.getValue(), type );
}
else {
setParameter( parameter, typedValue.getValue(), typedValue.getTypeReference() );
}
}
else {
locateBinding( parameter ).setBindValue( value, resolveJdbcParameterTypeIfNecessary() );
@ -963,27 +970,37 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
return this;
}
@SuppressWarnings( {"unchecked", "rawtypes"} )
private <P> void setParameter(Parameter<P> parameter, Object value, AllowableParameterType type) {
private <P> void setParameter(Parameter<P> parameter, P value, BasicTypeReference<P> type) {
setParameter( parameter, value, session.getTypeConfiguration().getBasicTypeRegistry().resolve( type ) );
}
private <P> void setParameter(Parameter<P> parameter, P value, AllowableParameterType<P> type) {
if ( parameter instanceof QueryParameter ) {
setParameter( (QueryParameter) parameter, value, type );
setParameter( (QueryParameter<P>) parameter, value, type );
}
else if ( value == null ) {
locateBinding( parameter ).setBindValue( null, type );
}
else if ( value instanceof Collection ) {
locateBinding( parameter ).setBindValues( (Collection) value );
locateBinding( parameter ).setBindValues( (Collection<P>) value );
}
else {
locateBinding( parameter ).setBindValue( (P) value, type );
locateBinding( parameter ).setBindValue( value, type );
}
}
@Override
public QueryImplementor<R> setParameter(String name, Object value) {
if ( value instanceof TypedParameterValue ) {
final TypedParameterValue typedValueWrapper = (TypedParameterValue) value;
return setParameter( name, typedValueWrapper.getValue(), typedValueWrapper.getType() );
@SuppressWarnings("unchecked")
final TypedParameterValue<Object> typedValue = (TypedParameterValue<Object>) value;
final AllowableParameterType<Object> type = typedValue.getType();
if ( type != null ) {
return setParameter( name, typedValue.getValue(), type );
}
else {
return setParameter( name, typedValue.getValue(), typedValue.getTypeReference() );
}
}
final QueryParameterImplementor<?> param = getParameterMetadata().getQueryParameter( name );
@ -1004,18 +1021,25 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@Override
public QueryImplementor<R> setParameter(int position, Object value) {
final QueryParameterImplementor<?> param = getParameterMetadata().getQueryParameter( position );
if ( value instanceof TypedParameterValue ) {
final TypedParameterValue typedParameterValue = (TypedParameterValue) value;
setParameter( param, typedParameterValue.getValue(), typedParameterValue.getType() );
@SuppressWarnings("unchecked")
final TypedParameterValue<Object> typedValue = (TypedParameterValue<Object>) value;
final AllowableParameterType<Object> type = typedValue.getType();
if ( type != null ) {
return setParameter( position, typedValue.getValue(), type );
}
else {
return setParameter( position, typedValue.getValue(), typedValue.getTypeReference() );
}
}
final QueryParameterImplementor<?> param = getParameterMetadata().getQueryParameter( position );
if ( param.allowsMultiValuedBinding() ) {
final AllowableParameterType<?> hibernateType = param.getHibernateType();
if ( hibernateType == null || ! hibernateType.getExpressableJavaTypeDescriptor().getJavaTypeClass().isInstance( value ) ) {
if ( value instanceof Collection ) {
//noinspection rawtypes
//noinspection rawtypes,unchecked
setParameterList( param, (Collection) value );
}
}
@ -1026,39 +1050,35 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings( {"unchecked", "rawtypes"} )
public <P> QueryImplementor<R> setParameter(QueryParameter<P> parameter, P value, AllowableParameterType type) {
public <P> QueryImplementor<R> setParameter(QueryParameter<P> parameter, P value, AllowableParameterType<P> type) {
locateBinding( parameter ).setBindValue( value, type );
return this;
}
@Override
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameter(String name, Object value, AllowableParameterType type) {
locateBinding( name ).setBindValue( value, type );
public <P> QueryImplementor<R> setParameter(String name, P value, AllowableParameterType<P> type) {
this.<P>locateBinding( name ).setBindValue( value, type );
return this;
}
@Override
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor setParameter(int position, Object value, AllowableParameterType type) {
locateBinding( position ).setBindValue( value, type );
public <P> QueryImplementor<R> setParameter(int position, P value, AllowableParameterType<P> type) {
this.<P>locateBinding( position ).setBindValue( value, type );
return this;
}
@Override
public QueryImplementor<R> setParameter(String name, Object value, BasicTypeReference<?> type) {
public <P> QueryImplementor<R> setParameter(String name, P value, BasicTypeReference<P> type) {
return setParameter( name, value, session.getTypeConfiguration().getBasicTypeRegistry().resolve( type ) );
}
@Override
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor setParameter(int position, Object value, BasicTypeReference<?> type) {
public <P> QueryImplementor<R> setParameter(int position, P value, BasicTypeReference<P> type) {
return setParameter( position, value, session.getTypeConfiguration().getBasicTypeRegistry().resolve( type ) );
}
@Override
public <P> Query<R> setParameter(QueryParameter<P> parameter, P val, BasicTypeReference<?> type) {
public <P> QueryImplementor<R> setParameter(QueryParameter<P> parameter, P val, BasicTypeReference<P> type) {
return setParameter( parameter, val, session.getTypeConfiguration().getBasicTypeRegistry().resolve( type ) );
}
@ -1087,30 +1107,26 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings( {"rawtypes", "unchecked"} )
public QueryImplementor<R> setParameterList(String name, Collection values) {
public QueryImplementor<R> setParameterList(String name, Collection<?> values) {
locateBinding( name ).setBindValues( values );
return this;
}
@Override
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(int position, Collection values) {
public QueryImplementor<R> setParameterList(int position, Collection<?> values) {
locateBinding( position ).setBindValues( values );
return this;
}
@Override
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(String name, Collection values, AllowableParameterType type) {
locateBinding( name ).setBindValues( values, type );
public <P> QueryImplementor<R> setParameterList(String name, Collection<? extends P> values, AllowableParameterType<P> type) {
this.<P>locateBinding( name ).setBindValues( values, type );
return this;
}
@Override
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(int position, Collection values, AllowableParameterType type) {
locateBinding( position ).setBindValues( values, type );
public <P> QueryImplementor<R> setParameterList(int position, Collection<? extends P> values, AllowableParameterType<P> type) {
this.<P>locateBinding( position ).setBindValues( values, type );
return this;
}
@ -1127,23 +1143,20 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(String name, Object[] values, AllowableParameterType type) {
locateBinding( name ).setBindValues( Arrays.asList( values ), type );
public QueryImplementor<R> setParameterList(String name, Object[] values, AllowableParameterType<?> type) {
locateBinding( name ).setBindValues( Arrays.asList( values ), (AllowableParameterType<Object>) type );
return this;
}
@Override
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(int position, Object[] values, AllowableParameterType type) {
locateBinding( position ).setBindValues( Arrays.asList( values ), type );
public QueryImplementor<R> setParameterList(int position, Object[] values, AllowableParameterType<?> type) {
locateBinding( position ).setBindValues( Arrays.asList( values ), (AllowableParameterType<Object>) type );
return this;
}
@Override
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(String name, Collection values, Class javaType) {
final JavaType javaDescriptor = getSession().getFactory()
public <P> QueryImplementor<R> setParameterList(String name, Collection<? extends P> values, Class<P> javaType) {
final JavaType<P> javaDescriptor = getSession().getFactory()
.getTypeConfiguration()
.getJavaTypeDescriptorRegistry()
.getDescriptor( javaType );
@ -1151,18 +1164,18 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
setParameterList( name, values );
}
else {
final AllowableParameterType paramType;
final BasicType basicType = getSession().getFactory().getTypeConfiguration().standardBasicTypeForJavaType( javaType );
final AllowableParameterType<P> paramType;
final BasicType<P> basicType = getSession().getFactory().getTypeConfiguration().standardBasicTypeForJavaType( javaType );
if ( basicType != null ) {
paramType = basicType;
}
else {
final ManagedDomainType managedDomainType = getSession().getFactory()
final ManagedDomainType<P> managedDomainType = getSession().getFactory()
.getRuntimeMetamodels()
.getJpaMetamodel()
.managedType( javaType );
if ( managedDomainType != null ) {
paramType = (AllowableParameterType) managedDomainType;
paramType = managedDomainType;
}
else {
throw new HibernateException( "Unable to determine AllowableParameterType : " + javaType.getName() );
@ -1176,9 +1189,8 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameterList(int position, Collection values, Class javaType) {
final JavaType javaDescriptor = getSession().getFactory()
public <P> QueryImplementor<R> setParameterList(int position, Collection<? extends P> values, Class<P> javaType) {
final JavaType<P> javaDescriptor = getSession().getFactory()
.getTypeConfiguration()
.getJavaTypeDescriptorRegistry()
.getDescriptor( javaType );
@ -1186,18 +1198,18 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
setParameterList( position, values );
}
else {
final AllowableParameterType paramType;
final BasicType basicType = getSession().getFactory().getTypeConfiguration().standardBasicTypeForJavaType( javaType );
final AllowableParameterType<P> paramType;
final BasicType<P> basicType = getSession().getFactory().getTypeConfiguration().standardBasicTypeForJavaType( javaType );
if ( basicType != null ) {
paramType = basicType;
}
else {
final ManagedDomainType managedDomainType = getSession().getFactory()
final ManagedDomainType<P> managedDomainType = getSession().getFactory()
.getRuntimeMetamodels()
.getJpaMetamodel()
.managedType( javaType );
if ( managedDomainType != null ) {
paramType = (AllowableParameterType) managedDomainType;
paramType = managedDomainType;
}
else {
throw new HibernateException( "Unable to determine AllowableParameterType : " + javaType.getName() );
@ -1211,16 +1223,14 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameter(Parameter<Calendar> param, Calendar value, TemporalType temporalType) {
locateBinding( (QueryParameter) param ).setBindValue( value, temporalType );
locateBinding( param ).setBindValue( value, temporalType );
return this;
}
@Override
@SuppressWarnings( {"unchecked", "rawtypes"} )
public QueryImplementor<R> setParameter(Parameter<Date> param, Date value, TemporalType temporalType) {
locateBinding( (QueryParameter) param ).setBindValue( value, temporalType );
locateBinding( param ).setBindValue( value, temporalType );
return this;
}
@ -1249,23 +1259,23 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@Override
@SuppressWarnings( {"unchecked", "rawtypes"} )
public <T> T getParameterValue(Parameter<T> param) {
QueryLogging.QUERY_LOGGER.tracef( "#getParameterValue(%s)", param );
getSession().checkOpen( false );
final QueryParameterImplementor qp = getParameterMetadata().resolve( param );
final QueryParameterImplementor<T> qp = getParameterMetadata().resolve( param );
if ( qp == null ) {
throw new IllegalArgumentException( "The parameter [" + param + "] is not part of this Query" );
}
final QueryParameterBinding binding = getQueryParameterBindings().getBinding( qp );
final QueryParameterBinding<T> binding = getQueryParameterBindings().getBinding( qp );
if ( binding == null || !binding.isBound() ) {
throw new IllegalStateException( "Parameter value not yet bound : " + param.toString() );
}
if ( binding.isMultiValued() ) {
//noinspection unchecked
return (T) binding.getBindValues();
}
else {
@ -1368,7 +1378,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
setParameterList( paramName, (Object[]) object );
}
else {
AllowableParameterType<?> type = determineType( paramName, retType );
AllowableParameterType<Object> type = determineType( paramName, retType );
setParameter( paramName, object, type );
}
}
@ -1380,7 +1390,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
}
@SuppressWarnings("WeakerAccess")
protected AllowableParameterType<?> determineType(String namedParam, Class<?> retType) {
protected AllowableParameterType<Object> determineType(String namedParam, Class<?> retType) {
AllowableParameterType<?> type = locateBinding( namedParam ).getBindType();
if ( type == null ) {
type = getParameterMetadata().getQueryParameter( namedParam ).getHibernateType();
@ -1388,7 +1398,8 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
if ( type == null && retType != null ) {
type = getSession().getFactory().resolveParameterBindType( retType );
}
return type;
//noinspection unchecked
return (AllowableParameterType<Object>) type;
}
@Override

View File

@ -38,5 +38,5 @@ public interface ParameterMetadataImplementor extends ParameterMetadata {
QueryParameterImplementor<?> getQueryParameter(int positionLabel);
@Override
QueryParameterImplementor<?> resolve(Parameter param);
<P> QueryParameterImplementor<P> resolve(Parameter<P> param);
}

View File

@ -87,21 +87,21 @@ public interface QueryParameterBinding<T> {
* @param values The bind values
*
*/
void setBindValues(Collection<T> values);
void setBindValues(Collection<? extends T> values);
/**
* Sets the parameter binding values using the explicit Type in regards to the individual values.
* @param values The bind values
* @param clarifiedType The explicit Type to use
*/
void setBindValues(Collection<T> values, AllowableParameterType<T> clarifiedType);
void setBindValues(Collection<? extends T> values, AllowableParameterType<T> clarifiedType);
/**Sets the parameter binding value using the explicit TemporalType in regards to the individual values.
*
* @param values The bind values
* @param temporalTypePrecision The temporal type to use
*/
void setBindValues(Collection<T> values, TemporalType temporalTypePrecision, TypeConfiguration typeConfiguration);
void setBindValues(Collection<? extends T> values, TemporalType temporalTypePrecision, TypeConfiguration typeConfiguration);
/**
* Get the values currently bound.

View File

@ -77,7 +77,6 @@ import org.hibernate.query.spi.MutableQueryOptions;
import org.hibernate.query.spi.NonSelectQueryPlan;
import org.hibernate.query.spi.ParameterMetadataImplementor;
import org.hibernate.query.spi.QueryEngine;
import org.hibernate.query.spi.QueryImplementor;
import org.hibernate.query.spi.QueryInterpretationCache;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.spi.QueryParameterImplementor;
@ -94,7 +93,6 @@ import org.hibernate.sql.exec.internal.CallbackImpl;
import org.hibernate.sql.exec.spi.Callback;
import org.hibernate.sql.exec.spi.ExecutionContext;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMappingProducer;
import org.hibernate.sql.results.spi.RowTransformer;
import org.hibernate.transform.ResultTransformer;
import org.hibernate.type.BasicType;
import org.hibernate.type.BasicTypeReference;
@ -727,7 +725,7 @@ public class NativeQueryImpl<R>
}
@Override
public NativeQueryImplementor<R> addScalar(String columnAlias, BasicDomainType type) {
public NativeQueryImplementor<R> addScalar(String columnAlias, BasicDomainType<?> type) {
return registerBuilder( Builders.scalar( columnAlias, (BasicType<?>) type ) );
}
@ -839,17 +837,17 @@ public class NativeQueryImpl<R>
}
@Override
public NativeQueryImplementor<R> addEntity(Class entityType) {
public NativeQueryImplementor<R> addEntity(Class<?> entityType) {
return addEntity( entityType.getName() );
}
@Override
public NativeQueryImplementor<R> addEntity(String tableAlias, Class entityClass) {
public NativeQueryImplementor<R> addEntity(String tableAlias, Class<?> entityClass) {
return addEntity( tableAlias, entityClass.getName() );
}
@Override
public NativeQueryImplementor<R> addEntity(String tableAlias, Class entityClass, LockMode lockMode) {
public NativeQueryImplementor<R> addEntity(String tableAlias, Class<?> entityClass, LockMode lockMode) {
return addEntity( tableAlias, entityClass.getName(), lockMode );
}
@ -924,7 +922,7 @@ public class NativeQueryImpl<R>
}
@Override
public NativeQueryImplementor<R> addSynchronizedEntityClass(Class entityClass) throws MappingException {
public NativeQueryImplementor<R> addSynchronizedEntityClass(Class<?> entityClass) throws MappingException {
addQuerySpaces( getSession().getFactory().getMetamodel().entityPersister( entityClass.getName() ).getQuerySpaces() );
return this;
}
@ -1083,9 +1081,8 @@ public class NativeQueryImpl<R>
}
@Override
@SuppressWarnings("unchecked")
public NativeQueryImplementor<R> setParameter(QueryParameter parameter, Object value) {
super.setParameter( (Parameter<Object>) parameter, value );
public <P> NativeQueryImplementor<R> setParameter(QueryParameter<P> parameter, P value) {
super.setParameter( parameter, value );
return this;
}
@ -1174,27 +1171,27 @@ public class NativeQueryImpl<R>
// }
@Override
public NativeQueryImplementor<R> setParameterList(String name, Collection values, AllowableParameterType type) {
//noinspection unchecked
return (NativeQueryImplementor) super.setParameterList( name, values, type );
public <P> NativeQueryImplementor<R> setParameterList(String name, Collection<? extends P> values, AllowableParameterType<P> type) {
super.setParameterList( name, values, type );
return this;
}
@Override
public NativeQueryImplementor<R> setParameterList(int position, Collection values, AllowableParameterType type) {
//noinspection unchecked
return (NativeQueryImplementor) super.setParameterList( position, values, type );
public <P> NativeQueryImplementor<R> setParameterList(int position, Collection<? extends P> values, AllowableParameterType<P> type) {
super.setParameterList( position, values, type );
return this;
}
@Override
public NativeQueryImplementor<R> setParameterList(String name, Object[] values, AllowableParameterType type) {
//noinspection unchecked
return (NativeQueryImplementor) super.setParameterList( name, values, type );
public NativeQueryImplementor<R> setParameterList(String name, Object[] values, AllowableParameterType<?> type) {
super.setParameterList( name, values, type );
return this;
}
@Override
public NativeQueryImplementor<R> setParameterList(int position, Object[] values, AllowableParameterType type) {
//noinspection unchecked
return (NativeQueryImplementor) super.setParameterList( position, values, type );
public NativeQueryImplementor<R> setParameterList(int position, Object[] values, AllowableParameterType<?> type) {
super.setParameterList( position, values, type );
return this;
}
// @Override
@ -1251,13 +1248,13 @@ public class NativeQueryImpl<R>
}
@Override
public NativeQueryImplementor<R> setParameterList(QueryParameter parameter, Collection values) {
public <P> NativeQueryImplementor<R> setParameterList(QueryParameter<P> parameter, Collection<P> values) {
super.setParameterList( parameter, values );
return this;
}
@Override
public NativeQueryImplementor<R> setParameterList(String name, Collection values) {
public NativeQueryImplementor<R> setParameterList(String name, Collection<?> values) {
super.setParameterList( name, values );
return this;
}
@ -1281,15 +1278,13 @@ public class NativeQueryImpl<R>
}
@Override
@SuppressWarnings("unchecked")
public NativeQueryImplementor<R> setParameter(Parameter param, Calendar value, TemporalType temporalType) {
public NativeQueryImplementor<R> setParameter(Parameter<Calendar> param, Calendar value, TemporalType temporalType) {
super.setParameter( param, value, temporalType );
return this;
}
@Override
@SuppressWarnings("unchecked")
public NativeQueryImplementor<R> setParameter(Parameter param, Date value, TemporalType temporalType) {
public NativeQueryImplementor<R> setParameter(Parameter<Date> param, Date value, TemporalType temporalType) {
super.setParameter( param, value, temporalType );
return this;
}
@ -1349,43 +1344,43 @@ public class NativeQueryImpl<R>
}
@Override
public <P> NativeQueryImplementor<R> setParameter(QueryParameter<P> parameter, P value, AllowableParameterType type) {
public <P> NativeQueryImplementor<R> setParameter(QueryParameter<P> parameter, P value, AllowableParameterType<P> type) {
super.setParameter( parameter, value, type );
return this;
}
@Override
public NativeQueryImplementor<R> setParameter(String name, Object value, AllowableParameterType type) {
public <P> NativeQueryImplementor<R> setParameter(String name, P value, AllowableParameterType<P> type) {
super.setParameter( name, value, type );
return this;
}
@Override
public NativeQueryImplementor<R> setParameter(int position, Object value, AllowableParameterType type) {
public <P> NativeQueryImplementor<R> setParameter(int position, P value, AllowableParameterType<P> type) {
super.setParameter( position, value, type );
return this;
}
@Override
public NativeQueryImplementor<R> setParameter(String name, Object value, BasicTypeReference<?> type) {
public <P> NativeQueryImplementor<R> setParameter(String name, P value, BasicTypeReference<P> type) {
super.setParameter( name, value, type );
return this;
}
@Override
public NativeQueryImplementor<R> setParameter(int position, Object value, BasicTypeReference<?> type) {
public <P> NativeQueryImplementor<R> setParameter(int position, P value, BasicTypeReference<P> type) {
super.setParameter( position, value, type );
return this;
}
@Override
public <P> NativeQueryImplementor<R> setParameter(QueryParameter<P> parameter, P val, BasicTypeReference<?> type) {
public <P> NativeQueryImplementor<R> setParameter(QueryParameter<P> parameter, P val, BasicTypeReference<P> type) {
super.setParameter( parameter, val, type );
return this;
}
@Override
public NativeQueryImplementor<R> setParameterList(int position, Collection values) {
public NativeQueryImplementor<R> setParameterList(int position, Collection<?> values) {
super.setParameterList( position, values );
return this;
}
@ -1397,13 +1392,13 @@ public class NativeQueryImpl<R>
}
@Override
public NativeQueryImplementor<R> setParameterList(String name, Collection values, Class javaType) {
public <P> NativeQueryImplementor<R> setParameterList(String name, Collection<? extends P> values, Class<P> javaType) {
super.setParameterList( name, values, javaType );
return this;
}
@Override
public NativeQueryImplementor<R> setParameterList(int position, Collection values, Class javaType) {
public <P> NativeQueryImplementor<R> setParameterList(int position, Collection<? extends P> values, Class<P> javaType) {
super.setParameterList( position, values, javaType );
return this;
}

View File

@ -66,7 +66,7 @@ public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQu
NativeQueryImplementor<R> addScalar(String columnAlias);
@Override
NativeQueryImplementor<R> addScalar(String columnAlias, BasicDomainType type);
NativeQueryImplementor<R> addScalar(String columnAlias, BasicDomainType<?> type);
@Override
NativeQueryImplementor<R> addScalar(String columnAlias, Class<?> javaType);
@ -109,13 +109,13 @@ public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQu
NativeQueryImplementor<R> addEntity(String tableAlias, String entityName, LockMode lockMode);
@Override
NativeQueryImplementor<R> addEntity(Class entityType);
NativeQueryImplementor<R> addEntity(Class<?> entityType);
@Override
NativeQueryImplementor<R> addEntity(String tableAlias, Class entityType);
NativeQueryImplementor<R> addEntity(String tableAlias, Class<?> entityType);
@Override
NativeQueryImplementor<R> addEntity(String tableAlias, Class entityClass, LockMode lockMode);
NativeQueryImplementor<R> addEntity(String tableAlias, Class<?> entityClass, LockMode lockMode);
@Override
NativeQueryImplementor<R> addJoin(String tableAlias, String path);
@ -136,7 +136,7 @@ public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQu
NativeQueryImplementor<R> addSynchronizedEntityName(String entityName) throws MappingException;
@Override
NativeQueryImplementor<R> addSynchronizedEntityClass(Class entityClass) throws MappingException;
NativeQueryImplementor<R> addSynchronizedEntityClass(Class<?> entityClass) throws MappingException;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -205,7 +205,7 @@ public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQu
// }
@Override
<P> NativeQueryImplementor<R> setParameter(QueryParameter<P> parameter, P val, AllowableParameterType type);
<P> NativeQueryImplementor<R> setParameter(QueryParameter<P> parameter, P val, AllowableParameterType<P> type);
@Override
NativeQueryImplementor<R> setParameter(int position, Object val);
@ -216,7 +216,7 @@ public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQu
// }
@Override
NativeQueryImplementor<R> setParameter(String name, Object val, AllowableParameterType type);
<P> NativeQueryImplementor<R> setParameter(String name, P val, AllowableParameterType<P> type);
// @Override
// default NativeQueryImplementor<R> setParameter(int position, Object val, Type type) {
@ -224,16 +224,16 @@ public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQu
// }
@Override
NativeQueryImplementor<R> setParameter(int position, Object val, AllowableParameterType type);
<P> NativeQueryImplementor<R> setParameter(int position, P val, AllowableParameterType<P> type);
@Override
NativeQueryImplementor<R> setParameter(String name, Object val, BasicTypeReference<?> type);
<P> NativeQueryImplementor<R> setParameter(String name, P val, BasicTypeReference<P> type);
@Override
NativeQueryImplementor<R> setParameter(int position, Object val, BasicTypeReference<?> type);
<P> NativeQueryImplementor<R> setParameter(int position, P val, BasicTypeReference<P> type);
@Override
<P> NativeQueryImplementor<R> setParameter(QueryParameter<P> parameter, P val, BasicTypeReference<?> type);
<P> NativeQueryImplementor<R> setParameter(QueryParameter<P> parameter, P val, BasicTypeReference<P> type);
@Override
<P> NativeQueryImplementor<R> setParameter(
@ -253,7 +253,7 @@ public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQu
Collection<P> values);
@Override
NativeQueryImplementor<R> setParameterList(String name, Collection values);
NativeQueryImplementor<R> setParameterList(String name, Collection<?> values);
// @Override
// default NativeQueryImplementor<R> setParameterList(String name, Collection values, Type type) {
@ -261,7 +261,7 @@ public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQu
// }
@Override
NativeQueryImplementor<R> setParameterList(String name, Collection values, AllowableParameterType type);
<P> NativeQueryImplementor<R> setParameterList(String name, Collection<? extends P> values, AllowableParameterType<P> type);
//
// @Override
// default NativeQueryImplementor<R> setParameterList(String name, Object[] values, Type type) {
@ -269,7 +269,7 @@ public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQu
// }
@Override
NativeQueryImplementor<R> setParameterList(String name, Object[] values, AllowableParameterType type);
NativeQueryImplementor<R> setParameterList(String name, Object[] values, AllowableParameterType<?> type);
@Override
NativeQueryImplementor<R> setParameterList(String name, Object[] values);
@ -353,25 +353,25 @@ public interface NativeQueryImplementor<R> extends QueryImplementor<R>, NativeQu
NativeQueryImplementor<R> setParameter(Parameter<OffsetDateTime> param, OffsetDateTime value, TemporalType temporalType);
@Override
NativeQueryImplementor<R> setParameterList(int position, Collection values);
NativeQueryImplementor<R> setParameterList(int position, Collection<?> values);
@Override
NativeQueryImplementor<R> setParameterList(String name, Collection values, Class type);
<P> NativeQueryImplementor<R> setParameterList(String name, Collection<? extends P> values, Class<P> type);
@Override
NativeQueryImplementor<R> setParameterList(int position, Collection values, Class type);
<P> NativeQueryImplementor<R> setParameterList(int position, Collection<? extends P> values, Class<P> type);
// @Override
// NativeQueryImplementor<R> setParameterList(int position, Collection values, Type type);
@Override
NativeQueryImplementor<R> setParameterList(int position, Collection values, AllowableParameterType type);
<P> NativeQueryImplementor<R> setParameterList(int position, Collection<? extends P> values, AllowableParameterType<P> type);
// @Override
// NativeQueryImplementor<R> setParameterList(int position, Object[] values, Type type);
@Override
NativeQueryImplementor<R> setParameterList(int position, Object[] values, AllowableParameterType type);
NativeQueryImplementor<R> setParameterList(int position, Object[] values, AllowableParameterType<?> type);
@Override
NativeQueryImplementor<R> setParameterList(int position, Object[] values);

View File

@ -8,6 +8,7 @@ package org.hibernate.query.sqm.sql;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@ -78,6 +79,8 @@ import org.hibernate.metamodel.model.domain.BasicDomainType;
import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
import org.hibernate.metamodel.model.domain.internal.CompositeSqmPathSource;
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
import org.hibernate.query.sqm.produce.function.internal.PatternRenderer;
import org.hibernate.sql.exec.internal.VersionTypeSeedParameterSpecification;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
@ -325,8 +328,9 @@ import static org.hibernate.query.BinaryArithmeticOperator.ADD;
import static org.hibernate.query.BinaryArithmeticOperator.MULTIPLY;
import static org.hibernate.query.BinaryArithmeticOperator.SUBTRACT;
import static org.hibernate.query.TemporalUnit.DAY;
import static org.hibernate.query.TemporalUnit.NANOSECOND;
import static org.hibernate.query.TemporalUnit.EPOCH;
import static org.hibernate.query.TemporalUnit.NATIVE;
import static org.hibernate.query.TemporalUnit.SECOND;
import static org.hibernate.query.UnaryArithmeticOperator.UNARY_MINUS;
import static org.hibernate.type.spi.TypeConfiguration.isDuration;
@ -2530,7 +2534,8 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
if ( isDuration( sqmPath.getNodeType() ) ) {
// Durations are stored (at least by default)
// in a BIGINTEGER column full of nanoseconds
// in a NUMERIC column in seconds with fractional
// seconds in the decimal places
// which we need to convert to the given unit
//
// This does not work at all for a Duration
@ -2545,7 +2550,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
//first let's apply the propagated scale
Expression scaledExpression = applyScale( toSqlExpression( path ) );
// we use NANOSECOND, not NATIVE, as the unit
// we use SECOND, not NATIVE, as the unit
// because that's how a Duration is persisted
// in a database table column, and how it's
// returned to a Java client
@ -2559,7 +2564,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
// adjusted date or timestamp
result = timestampadd().expression(
(AllowableFunctionReturnType<?>) adjustedTimestampType,
new DurationUnit( NANOSECOND, basicType( Long.class ) ),
new DurationUnit( SECOND, basicType( Long.class ) ),
scaledExpression,
adjustedTimestamp
);
@ -2571,7 +2576,23 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
// nanoseconds to the given unit
JdbcMappingContainer durationType = scaledExpression.getExpressionType();
Duration duration = new Duration( scaledExpression, NANOSECOND, (BasicValuedMapping) durationType );
Duration duration;
if ( durationType.getJdbcMappings()
.get( 0 )
.getJdbcTypeDescriptor()
.isInterval() ) {
// For interval types, we need to extract the epoch for integer arithmetic for the 'by unit' operator
duration = new Duration(
extractEpoch( scaledExpression ),
SECOND,
(BasicValuedMapping) durationType
);
}
else {
// The absolute value of the expression is in seconds
// as the fractional seconds are in the fraction part as can be seen in DurationJavaType
duration = new Duration( scaledExpression, SECOND, (BasicValuedMapping) durationType );
}
TemporalUnit appliedUnit = appliedByUnit.getUnit().getUnit();
BasicValuedMapping scalarType = (BasicValuedMapping) appliedByUnit.getNodeType();
@ -2586,6 +2607,23 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
return withTreatRestriction( result, sqmPath );
}
private Expression extractEpoch(Expression intervalExpression) {
final BasicType<Integer> intType = getTypeConfiguration().getBasicTypeForJavaType( Integer.class );
return new SelfRenderingFunctionSqlAstExpression(
"extract",
(sqlAppender, sqlAstArguments, walker) ->
new PatternRenderer(
creationContext.getSessionFactory()
.getJdbcServices()
.getDialect()
.extractPattern( EPOCH )
).render( sqlAppender, sqlAstArguments, walker ),
Arrays.asList( new ExtractUnit( EPOCH, intType ), intervalExpression ),
intType,
intType
);
}
@Override
public Expression visitEmbeddableValuedPath(SqmEmbeddedValuedSimplePath<?> sqmPath) {
return withTreatRestriction(
@ -4083,13 +4121,10 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
// the diff, and then the subsequent add
DurationUnit unit = new DurationUnit( baseUnit, basicType( Integer.class ) );
Expression scaledMagnitude = applyScale( timestampdiff().expression(
(AllowableFunctionReturnType<?>) expression.getNodeType(),
unit, right, left
) );
Expression magnitude = applyScale( timestampdiff().expression( null, unit, right, left ) );
return timestampadd().expression(
(AllowableFunctionReturnType<?>) adjustedTimestampType, //TODO should be adjustedTimestamp.getType()
unit, scaledMagnitude, adjustedTimestamp
unit, magnitude, adjustedTimestamp
);
}
else if ( appliedByUnit != null ) {
@ -4097,10 +4132,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
// duration to a scalar in the given unit
DurationUnit unit = (DurationUnit) appliedByUnit.getUnit().accept( this );
return applyScale( timestampdiff().expression(
(AllowableFunctionReturnType<?>) expression.getNodeType(),
unit, right, left
) );
return applyScale( timestampdiff().expression( null, unit, right, left ) );
}
else {
// a plain "bare" Duration
@ -4180,14 +4212,22 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
magnitude = adjustmentScale;
}
else {
final BasicValuedMapping magnitudeType = (BasicValuedMapping) magnitude.getExpressionType();
final BasicValuedMapping expressionType;
if ( magnitudeType.getJdbcMapping().getJdbcTypeDescriptor().isInterval() ) {
expressionType = magnitudeType;
}
else {
expressionType = widestNumeric(
(BasicValuedMapping) adjustmentScale.getExpressionType(),
magnitudeType
);
}
magnitude = new BinaryArithmeticExpression(
adjustmentScale,
MULTIPLY,
magnitude,
widestNumeric(
(BasicValuedMapping) adjustmentScale.getExpressionType(),
(BasicValuedMapping) magnitude.getExpressionType()
)
expressionType
);
}
}
@ -4236,7 +4276,17 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
}
else {
BasicValuedMapping durationType = (BasicValuedMapping) toDuration.getNodeType();
Duration duration = new Duration( scaledMagnitude, unit.getUnit(), durationType );
Duration duration;
if ( scaledMagnitude.getExpressionType()
.getJdbcMappings()
.get( 0 )
.getJdbcTypeDescriptor()
.isInterval() ) {
duration = new Duration( extractEpoch( scaledMagnitude ), SECOND, durationType );
}
else {
duration = new Duration( scaledMagnitude, unit.getUnit(), durationType );
}
if ( appliedByUnit != null ) {
// we're applying the 'by unit' operator,

View File

@ -280,6 +280,11 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
return delegate();
}
@Override
public SessionFactoryImplementor getSessionFactory() {
return sessionFactory;
}
@Override
public boolean useStreamForLobBinding() {
return sessionFactory.getFastSessionServices().useStreamForLobBinding();
@ -367,6 +372,11 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
sqlBuffer.append( value );
}
@Override
public void appendSql(long value) {
sqlBuffer.append( value );
}
@Override
public void appendSql(boolean value) {
sqlBuffer.append( value );
@ -3742,9 +3752,10 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
@Override
public void visitConversion(Conversion conversion) {
conversion.getDuration().getMagnitude().accept( this );
final Duration duration = conversion.getDuration();
duration.getMagnitude().accept( this );
appendSql(
conversion.getDuration().getUnit().conversionFactor(
duration.getUnit().conversionFactor(
conversion.getUnit(), getDialect()
)
);

View File

@ -39,6 +39,10 @@ public interface SqlAppender extends Appendable {
appendSql( Integer.toString( value ) );
}
default void appendSql(long value) {
appendSql( Long.toString( value ) );
}
default void appendSql(boolean value) {
appendSql( String.valueOf( value ) );
}

View File

@ -115,6 +115,16 @@ public interface ResultSetAccess extends JdbcValuesMetadata {
return length;
}
@Override
public int getColumnPrecision() {
return precision;
}
@Override
public int getColumnScale() {
return scale;
}
@Override
public EnumType getEnumeratedType() {
return resolvedJdbcType.isNumber() ? EnumType.ORDINAL : EnumType.STRING;

View File

@ -27,11 +27,6 @@ public abstract class AbstractSingleColumnStandardBasicType<T>
super( jdbcType, javaTypeDescriptor );
}
@Override
public final int getJdbcTypeCode() {
return getJdbcTypeDescriptor().getJdbcTypeCode();
}
@Override
public final void nullSafeSet(PreparedStatement st, Object value, int index, boolean[] settable, SharedSessionContractImplementor session)
throws HibernateException, SQLException {

View File

@ -39,7 +39,7 @@ import org.hibernate.type.descriptor.jdbc.JdbcType;
* @author Brett Meyer
*/
public abstract class AbstractStandardBasicType<T>
implements BasicType<T>, StringRepresentableType<T>, ProcedureParameterExtractionAware<T>, ProcedureParameterNamedBinder {
implements BasicType<T>, ProcedureParameterExtractionAware<T>, ProcedureParameterNamedBinder<T> {
private static final Size DEFAULT_SIZE = new Size( 19, 2, 255, Size.LobMultiplier.NONE ); // to match legacy behavior
private final Size dictatedSize = new Size();
@ -92,16 +92,6 @@ public abstract class AbstractStandardBasicType<T>
return javaTypeDescriptor.fromString( string );
}
@Override
public String toString(T value) {
return javaTypeDescriptor.toString( value );
}
@Override
public T fromStringValue(CharSequence charSequence) throws HibernateException {
return javaTypeDescriptor.fromString( charSequence );
}
protected MutabilityPlan<T> getMutabilityPlan() {
return javaTypeDescriptor.getMutabilityPlan();
}
@ -295,16 +285,16 @@ public abstract class AbstractStandardBasicType<T>
Object value,
int index,
final SharedSessionContractImplementor session) throws SQLException {
nullSafeSet( st, value, index, (WrapperOptions) session );
//noinspection unchecked
nullSafeSet( st, (T) value, index, (WrapperOptions) session );
}
@SuppressWarnings({ "unchecked" })
protected void nullSafeSet(PreparedStatement st, Object value, int index, WrapperOptions options) throws SQLException {
jdbcType.getBinder( javaTypeDescriptor ).bind( st, ( T ) value, index, options );
protected void nullSafeSet(PreparedStatement st, T value, int index, WrapperOptions options) throws SQLException {
jdbcType.getBinder( javaTypeDescriptor ).bind( st, value, index, options );
}
public void set(PreparedStatement st, T value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
nullSafeSet( st, value, index, session );
nullSafeSet( st, value, index, (WrapperOptions) session );
}
@Override
@ -430,7 +420,7 @@ public abstract class AbstractStandardBasicType<T>
}
@Override
public void nullSafeSet(CallableStatement st, Object value, String name, SharedSessionContractImplementor session) throws SQLException {
public void nullSafeSet(CallableStatement st, T value, String name, SharedSessionContractImplementor session) throws SQLException {
nullSafeSet( st, value, name, (WrapperOptions) session );
}

View File

@ -6,6 +6,8 @@
*/
package org.hibernate.type;
import java.io.Serializable;
import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
/**
@ -13,7 +15,7 @@ import org.hibernate.metamodel.model.convert.spi.BasicValueConverter;
*
* @author Christian Beikov
*/
public final class BasicTypeReference<T> {
public final class BasicTypeReference<T> implements Serializable {
private final String name;
private final Class<? extends T> javaType;
private final int sqlTypeCode;

View File

@ -252,7 +252,7 @@ public class BasicTypeRegistry implements Serializable {
}
public void register(UserType type, String... keys) {
register( new CustomType( type, keys, typeConfiguration ) );
register( new CustomType<Object>( type, keys, typeConfiguration ) );
}
public void unregister(String... keys) {

View File

@ -50,48 +50,48 @@ import org.hibernate.usertype.UserVersionType;
* @author Gavin King
* @author Steve Ebersole
*/
public class CustomType
public class CustomType<J>
extends AbstractType
implements BasicType, StringRepresentableType, ProcedureParameterNamedBinder, ProcedureParameterExtractionAware {
implements BasicType<J>, ProcedureParameterNamedBinder<J>, ProcedureParameterExtractionAware<J> {
private final UserType<Object> userType;
private final UserType<J> userType;
private final String[] registrationKeys;
private final String name;
private final BasicJavaType<Object> mappedJavaTypeDescriptor;
private final BasicJavaType<J> mappedJavaTypeDescriptor;
private final JdbcType jdbcType;
private final ValueExtractor<Object> valueExtractor;
private final ValueBinder<Object> valueBinder;
private final ValueExtractor<J> valueExtractor;
private final ValueBinder<J> valueBinder;
private final Size dictatedSize;
private final Size defaultSize;
public CustomType(UserType userType, TypeConfiguration typeConfiguration) throws MappingException {
public CustomType(UserType<J> userType, TypeConfiguration typeConfiguration) throws MappingException {
this( userType, ArrayHelper.EMPTY_STRING_ARRAY, typeConfiguration );
}
public CustomType(UserType userType, String[] registrationKeys, TypeConfiguration typeConfiguration) throws MappingException {
public CustomType(UserType<J> userType, String[] registrationKeys, TypeConfiguration typeConfiguration) throws MappingException {
this.userType = userType;
this.name = userType.getClass().getName();
if ( userType instanceof BasicJavaType ) {
//noinspection rawtypes
this.mappedJavaTypeDescriptor = ( (BasicJavaType) userType );
//noinspection unchecked
this.mappedJavaTypeDescriptor = ( (BasicJavaType<J>) userType );
}
else if ( userType instanceof JavaTypedExpressable ) {
//noinspection rawtypes
this.mappedJavaTypeDescriptor = (BasicJavaType) ( (JavaTypedExpressable) userType ).getExpressableJavaTypeDescriptor();
//noinspection unchecked
this.mappedJavaTypeDescriptor = (BasicJavaType<J>) ( (JavaTypedExpressable<J>) userType ).getExpressableJavaTypeDescriptor();
}
else if ( userType instanceof UserVersionType ) {
this.mappedJavaTypeDescriptor = new UserTypeVersionJavaTypeWrapper<>( (UserVersionType) userType );
this.mappedJavaTypeDescriptor = new UserTypeVersionJavaTypeWrapper<>( (UserVersionType<J>) userType );
}
else {
this.mappedJavaTypeDescriptor = new UserTypeJavaTypeWrapper<>( userType );
}
// create a JdbcType adapter that uses the UserType binde/extract handling
// create a JdbcType adapter that uses the UserType binder/extract handling
this.jdbcType = new UserTypeSqlTypeAdapter<>( userType, mappedJavaTypeDescriptor );
this.valueExtractor = jdbcType.getExtractor( mappedJavaTypeDescriptor );
@ -110,17 +110,17 @@ public class CustomType
this.registrationKeys = registrationKeys;
}
public UserType getUserType() {
public UserType<J> getUserType() {
return userType;
}
@Override
public ValueExtractor getJdbcValueExtractor() {
public ValueExtractor<J> getJdbcValueExtractor() {
return valueExtractor;
}
@Override
public ValueBinder<?> getJdbcValueBinder() {
public ValueBinder<J> getJdbcValueBinder() {
return valueBinder;
}
@ -155,7 +155,7 @@ public class CustomType
}
@Override
public Class getReturnedClass() {
public Class<J> getReturnedClass() {
return getUserType().returnedClass();
}
@ -215,7 +215,7 @@ public class CustomType
boolean[] settable,
SharedSessionContractImplementor session) throws SQLException {
if ( settable[0] ) {
getUserType().nullSafeSet( st, value, index, session );
getUserType().nullSafeSet( st, (J) value, index, session );
}
}
@ -225,17 +225,7 @@ public class CustomType
Object value,
int index,
SharedSessionContractImplementor session) throws SQLException {
getUserType().nullSafeSet( st, value, index, session );
}
@SuppressWarnings({ "UnusedDeclaration" })
public String toXMLString(Object value, SessionFactoryImplementor factory) {
return toString( value );
}
@SuppressWarnings({ "UnusedDeclaration" })
public Object fromXMLString(String xml, Mapping factory) {
return fromStringValue( xml );
getUserType().nullSafeSet( st, (J) value, index, session );
}
@Override
@ -258,8 +248,11 @@ public class CustomType
if ( value == null ) {
return "null";
}
else if ( userType instanceof EnhancedUserType<?> ) {
return ( (EnhancedUserType<Object>) userType ).toString( value );
}
else {
return toXMLString( value, factory );
return value.toString();
}
}
@ -278,41 +271,6 @@ public class CustomType
return checkable[0] && isDirty(old, current, session);
}
@Override
@SuppressWarnings("unchecked")
public String toString(Object value) throws HibernateException {
if ( getUserType() instanceof StringRepresentableType ) {
return ( (StringRepresentableType) getUserType() ).toString( value );
}
if ( value == null ) {
return null;
}
if ( getUserType() instanceof EnhancedUserType ) {
//noinspection deprecation
return ( (EnhancedUserType) getUserType() ).toXMLString( value );
}
return value.toString();
}
@Override
public Object fromStringValue(CharSequence sequence) throws HibernateException {
if ( getUserType() instanceof StringRepresentableType ) {
return ( (StringRepresentableType) getUserType() ).fromStringValue( sequence );
}
if ( getUserType() instanceof EnhancedUserType ) {
//noinspection deprecation
return ( (EnhancedUserType) getUserType() ).fromXMLString( sequence );
}
throw new HibernateException(
String.format(
"Could not process #fromStringValue, UserType class [%s] did not implement %s or %s",
name,
StringRepresentableType.class.getName(),
EnhancedUserType.class.getName()
)
);
}
@Override
public boolean canDoSetting() {
if ( getUserType() instanceof ProcedureParameterNamedBinder ) {
@ -323,9 +281,9 @@ public class CustomType
@Override
public void nullSafeSet(
CallableStatement statement, Object value, String name, SharedSessionContractImplementor session) throws SQLException {
CallableStatement statement, J value, String name, SharedSessionContractImplementor session) throws SQLException {
if ( canDoSetting() ) {
((ProcedureParameterNamedBinder) getUserType() ).nullSafeSet( statement, value, name, session );
((ProcedureParameterNamedBinder<J>) getUserType() ).nullSafeSet( statement, value, name, session );
}
else {
throw new UnsupportedOperationException(
@ -337,15 +295,16 @@ public class CustomType
@Override
public boolean canDoExtraction() {
if ( getUserType() instanceof ProcedureParameterExtractionAware ) {
return ((ProcedureParameterExtractionAware) getUserType() ).canDoExtraction();
return ((ProcedureParameterExtractionAware<?>) getUserType() ).canDoExtraction();
}
return false;
}
@Override
public Object extract(CallableStatement statement, int startIndex, SharedSessionContractImplementor session) throws SQLException {
public J extract(CallableStatement statement, int startIndex, SharedSessionContractImplementor session) throws SQLException {
if ( canDoExtraction() ) {
return ((ProcedureParameterExtractionAware) getUserType() ).extract( statement, startIndex, session );
//noinspection unchecked
return ((ProcedureParameterExtractionAware<J>) getUserType() ).extract( statement, startIndex, session );
}
else {
throw new UnsupportedOperationException(
@ -355,10 +314,11 @@ public class CustomType
}
@Override
public Object extract(CallableStatement statement, String paramName, SharedSessionContractImplementor session)
public J extract(CallableStatement statement, String paramName, SharedSessionContractImplementor session)
throws SQLException {
if ( canDoExtraction() ) {
return ((ProcedureParameterExtractionAware) getUserType() ).extract( statement, paramName, session );
//noinspection unchecked
return ((ProcedureParameterExtractionAware<J>) getUserType() ).extract( statement, paramName, session );
}
else {
throw new UnsupportedOperationException(
@ -374,26 +334,26 @@ public class CustomType
@Override
public boolean equals(Object obj) {
return ( obj instanceof CustomType ) && getUserType().equals( ( (CustomType) obj ).getUserType() );
return ( obj instanceof CustomType ) && getUserType().equals( ( (CustomType<?>) obj ).getUserType() );
}
@Override
public Class getJavaType() {
public Class<J> getJavaType() {
return mappedJavaTypeDescriptor.getJavaTypeClass();
}
@Override
public JavaType getMappedJavaTypeDescriptor() {
public JavaType<J> getMappedJavaTypeDescriptor() {
return mappedJavaTypeDescriptor;
}
@Override
public JavaType getExpressableJavaTypeDescriptor() {
public JavaType<J> getExpressableJavaTypeDescriptor() {
return getMappedJavaTypeDescriptor();
}
@Override
public JavaType getJavaTypeDescriptor() {
public JavaType<J> getJavaTypeDescriptor() {
return getMappedJavaTypeDescriptor();
}
}

View File

@ -6,6 +6,7 @@
*/
package org.hibernate.type;
import java.sql.Timestamp;
import java.util.Date;
import org.hibernate.internal.CoreMessageLogger;
@ -19,8 +20,8 @@ import org.hibernate.type.descriptor.jdbc.TimestampJdbcType;
import org.jboss.logging.Logger;
/**
* <tt>dbtimestamp</tt>: An extension of {@link TimestampType} which
* maps to the database's current timestamp, rather than the jvm's
* <tt>dbtimestamp</tt>: A type that maps between {@link java.sql.Types#TIMESTAMP TIMESTAMP} and {@link Timestamp}.
* It maps to the database's current timestamp, rather than the jvm's
* current timestamp.
* <p/>
* Note: May/may-not cause issues on dialects which do not properly support
@ -29,20 +30,12 @@ import org.jboss.logging.Logger;
*
* @author Steve Ebersole
*/
public class DbTimestampType extends TimestampType {
public class DbTimestampType extends AbstractSingleColumnStandardBasicType<Date> {
public static final DbTimestampType INSTANCE = new DbTimestampType();
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
DbTimestampType.class.getName()
);
public DbTimestampType() {
this( TimestampJdbcType.INSTANCE, JdbcTimestampJavaTypeDescriptor.INSTANCE );
}
public DbTimestampType(JdbcType jdbcType, JavaType<Date> javaTypeDescriptor) {
super( jdbcType, new DbTimestampJavaTypeDescriptor<>( (TemporalJavaTypeDescriptor<Date>) javaTypeDescriptor ) );
private DbTimestampType() {
super( TimestampJdbcType.INSTANCE, new DbTimestampJavaTypeDescriptor<>( JdbcTimestampJavaTypeDescriptor.INSTANCE ) );
}
@Override

View File

@ -70,7 +70,7 @@ import org.jboss.logging.Logger;
*/
@SuppressWarnings("unchecked")
public class EnumType<T extends Enum<T>>
implements EnhancedUserType, DynamicParameterizedType, LoggableUserType, TypeConfigurationAware, Serializable {
implements EnhancedUserType<T>, DynamicParameterizedType, LoggableUserType, TypeConfigurationAware, Serializable {
private static final Logger LOG = CoreLogging.logger( EnumType.class );
public static final String ENUM = "enumClass";
@ -350,7 +350,7 @@ public class EnumType<T extends Enum<T>>
}
@Override
public Class<? extends Enum> returnedClass() {
public Class<T> returnedClass() {
return enumClass;
}
@ -365,7 +365,7 @@ public class EnumType<T extends Enum<T>>
}
@Override
public Object nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner) throws SQLException {
public T nullSafeGet(ResultSet rs, int position, SharedSessionContractImplementor session, Object owner) throws SQLException {
verifyConfigured();
final Object relational = jdbcValueExtractor.extract( rs, position, session );
return enumValueConverter.toDomainValue( relational );
@ -378,9 +378,9 @@ public class EnumType<T extends Enum<T>>
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
public void nullSafeSet(PreparedStatement st, T value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
verifyConfigured();
enumValueConverter.writeValue( st, (T) value, index, session );
enumValueConverter.writeValue( st, value, index, session );
}
@Override
@ -419,22 +419,21 @@ public class EnumType<T extends Enum<T>>
}
@Override
public String objectToSQLString(Object value) {
public String toSqlLiteral(T value) {
verifyConfigured();
return enumValueConverter.toSqlLiteral( value );
}
@Override
public String toXMLString(Object value) {
public String toString(T value) {
verifyConfigured();
return enumValueConverter.getDomainJavaDescriptor().unwrap( (T) value, String.class, null );
return enumValueConverter.getDomainJavaDescriptor().unwrap( value, String.class, null );
}
@Override
@SuppressWarnings("RedundantCast")
public Object fromXMLString(CharSequence xmlValue) {
public T fromStringValue(CharSequence sequence) {
verifyConfigured();
return (T) enumValueConverter.getDomainJavaDescriptor().wrap( xmlValue, null );
return enumValueConverter.getDomainJavaDescriptor().wrap( sequence, null );
}
@Override

View File

@ -0,0 +1,28 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* 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.type;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType;
/**
* A mapper for mapping objects to and from a format.
*
* @author Christian Beikov
*/
public interface FormatMapper {
/**
* Deserializes an object from the character sequence.
*/
<T> T fromString(CharSequence charSequence, JavaType<T> javaType, WrapperOptions wrapperOptions);
/**
* Serializes the object to a string.
*/
<T> String toString(T value, JavaType<T> javaType, WrapperOptions wrapperOptions);
}

View File

@ -0,0 +1,53 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* 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.type;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* @author Christian Beikov
*/
public class JacksonJsonFormatMapper implements FormatMapper {
public static final String SHORT_NAME = "jackson";
public static final JacksonJsonFormatMapper INSTANCE = new JacksonJsonFormatMapper();
private final ObjectMapper objectMapper;
public JacksonJsonFormatMapper() {
this(new ObjectMapper());
}
public JacksonJsonFormatMapper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override
public <T> T fromString(CharSequence charSequence, JavaType<T> javaType, WrapperOptions wrapperOptions) {
try {
return objectMapper.readValue( charSequence.toString(), objectMapper.constructType( javaType.getJavaType() ) );
}
catch (JsonProcessingException e) {
throw new IllegalArgumentException( "Could not deserialize string to java type: " + javaType, e );
}
}
@Override
public <T> String toString(T value, JavaType<T> javaType, WrapperOptions wrapperOptions) {
try {
return objectMapper.writerFor( objectMapper.constructType( javaType.getJavaType() ) )
.writeValueAsString( value );
}
catch (JsonProcessingException e) {
throw new IllegalArgumentException( "Could not serialize object of java type: " + javaType, e );
}
}
}

View File

@ -0,0 +1,53 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* 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.type;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaType;
import jakarta.json.bind.Jsonb;
import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.JsonbException;
/**
* @author Christian Beikov
*/
public class JsonBJsonFormatMapper implements FormatMapper {
public static final String SHORT_NAME = "jsonb";
public static final JsonBJsonFormatMapper INSTANCE = new JsonBJsonFormatMapper();
private final Jsonb jsonb;
public JsonBJsonFormatMapper() {
this( JsonbBuilder.create() );
}
public JsonBJsonFormatMapper(Jsonb jsonb) {
this.jsonb = jsonb;
}
@Override
public <T> T fromString(CharSequence charSequence, JavaType<T> javaType, WrapperOptions wrapperOptions) {
try {
return jsonb.fromJson( charSequence.toString(), javaType.getJavaType() );
}
catch (JsonbException e) {
throw new IllegalArgumentException( "Could not deserialize string to java type: " + javaType, e );
}
}
@Override
public <T> String toString(T value, JavaType<T> javaType, WrapperOptions wrapperOptions) {
try {
return jsonb.toJson( value, javaType.getJavaType() );
}
catch (JsonbException e) {
throw new IllegalArgumentException( "Could not serialize object of java type: " + javaType, e );
}
}
}

View File

@ -1,138 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* 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.type;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.UUID;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.ValueExtractor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.BasicJavaType;
import org.hibernate.type.descriptor.java.JavaType;
import org.hibernate.type.descriptor.java.UUIDJavaTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.BasicBinder;
import org.hibernate.type.descriptor.jdbc.BasicExtractor;
import org.hibernate.type.descriptor.jdbc.JdbcLiteralFormatter;
import org.hibernate.type.descriptor.jdbc.JdbcType;
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeDescriptorRegistry;
import org.hibernate.type.spi.TypeConfiguration;
/**
* Specialized type mapping for {@link UUID} and the Postgres UUID data type (which is mapped as OTHER in its
* JDBC driver).
*
* @author Steve Ebersole
* @author David Driscoll
*/
public class PostgresUUIDType extends AbstractSingleColumnStandardBasicType<UUID> {
public static final PostgresUUIDType INSTANCE = new PostgresUUIDType();
public PostgresUUIDType() {
super( PostgresUUIDJdbcType.INSTANCE, UUIDJavaTypeDescriptor.INSTANCE );
}
public String getName() {
return "pg-uuid";
}
@Override
protected boolean registerUnderJavaType() {
// register this type under UUID when it is added to the basic type registry
return true;
}
public static class PostgresUUIDJdbcType implements JdbcType {
/**
* Singleton access
*/
public static final PostgresUUIDJdbcType INSTANCE = new PostgresUUIDJdbcType();
/**
* Postgres reports its UUID type as {@link Types#OTHER}. Unfortunately
* it reports a lot of its types as {@link Types#OTHER}, making that
* value useless for distinguishing one SqlTypeDescriptor from another.
* So here we define a "magic value" that is a (hopefully no collisions)
* unique key within the {@link JdbcTypeDescriptorRegistry}
*/
private static final int JDBC_TYPE_CODE = 3975;
@Override
public int getJdbcTypeCode() {
return JDBC_TYPE_CODE;
}
@Override
public <J> BasicJavaType<J> getJdbcRecommendedJavaTypeMapping(
Integer length,
Integer scale,
TypeConfiguration typeConfiguration) {
return (BasicJavaType<J>) typeConfiguration.getJavaTypeDescriptorRegistry().resolveDescriptor( UUID.class );
}
@Override
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaTypeDescriptor) {
return null;
}
@Override
public <X> ValueBinder<X> getBinder(JavaType<X> javaTypeDescriptor) {
return new BasicBinder<X>( javaTypeDescriptor, this ) {
@Override
protected void doBindNull(PreparedStatement st, int index, WrapperOptions wrapperOptions) throws SQLException {
st.setNull( index, Types.OTHER );
}
@Override
protected void doBind(
PreparedStatement st,
X value,
int index,
WrapperOptions wrapperOptions) throws SQLException {
st.setObject( index, javaTypeDescriptor.unwrap( value, UUID.class, wrapperOptions ), Types.OTHER );
}
@Override
protected void doBindNull(CallableStatement st, String name, WrapperOptions wrapperOptions) throws SQLException {
st.setNull( name, Types.OTHER );
}
@Override
protected void doBind(
CallableStatement st,
X value,
String name,
WrapperOptions wrapperOptions) throws SQLException {
st.setObject( name, javaTypeDescriptor.unwrap( value, UUID.class, wrapperOptions ), Types.OTHER );
}
};
}
@Override
public <X> ValueExtractor<X> getExtractor(JavaType<X> javaTypeDescriptor) {
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
@Override
protected X doExtract(ResultSet rs, int position, WrapperOptions wrapperOptions) throws SQLException {
return javaTypeDescriptor.wrap( rs.getObject( position ), wrapperOptions );
}
@Override
protected X doExtract(CallableStatement statement, int position, WrapperOptions wrapperOptions) throws SQLException {
return javaTypeDescriptor.wrap( statement.getObject( position ), wrapperOptions );
}
@Override
protected X doExtract(CallableStatement statement, String name, WrapperOptions wrapperOptions) throws SQLException {
return javaTypeDescriptor.wrap( statement.getObject( name ), wrapperOptions );
}
};
}
}
}

View File

@ -18,7 +18,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
*
* @author Andrea Boriero
*/
public interface ProcedureParameterNamedBinder {
public interface ProcedureParameterNamedBinder<J> {
/**
* Can the given instance of this type actually set the parameter value by name
@ -40,5 +40,5 @@ public interface ProcedureParameterNamedBinder {
* @throws HibernateException An error from Hibernate
* @throws SQLException An error from the JDBC driver
*/
void nullSafeSet(CallableStatement statement, Object value, String name, SharedSessionContractImplementor session) throws SQLException;
void nullSafeSet(CallableStatement statement, J value, String name, SharedSessionContractImplementor session) throws SQLException;
}

View File

@ -1,38 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* 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.type;
import org.hibernate.type.descriptor.java.RowVersionJavaTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.VarbinaryJdbcType;
/**
* A type that maps between a {@link java.sql.Types#VARBINARY VARBINARY} and {@code byte[]}
* specifically for entity versions/timestamps.
*
* @author Gavin King
* @author Steve Ebersole
* @author Gail Badner
*/
public class RowVersionType
extends AbstractSingleColumnStandardBasicType<byte[]> {
public static final RowVersionType INSTANCE = new RowVersionType();
public String getName() {
return "row_version";
}
public RowVersionType() {
super( VarbinaryJdbcType.INSTANCE, RowVersionJavaTypeDescriptor.INSTANCE );
}
@Override
public String[] getRegistrationKeys() {
return new String[] { getName() };
}
}

View File

@ -20,12 +20,6 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
*/
public interface SingleColumnType<T> extends Type {
int getJdbcTypeCode();
String toString(T value) throws HibernateException;
T fromStringValue(CharSequence sequence) throws HibernateException;
/**
* Get a column value from a result set by name.
*

View File

@ -0,0 +1,413 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* 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.type;
import java.sql.Types;
/**
* The class that defines the constants that are used to identify generic
* SQL types. This is an extension of {@link Types} that provides type codes
* for types that Hibernate supports in addition to the standard JDBC types.
*
* @author Christian Beikov
*/
public class SqlTypes {
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code BIT}.
*
* @see Types#BIT
*/
public final static int BIT = Types.BIT;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code TINYINT}.
*
* @see Types#TINYINT
*/
public final static int TINYINT = Types.TINYINT;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code SMALLINT}.
*
* @see Types#SMALLINT
*/
public final static int SMALLINT = Types.SMALLINT;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code INTEGER}.
*
* @see Types#INTEGER
*/
public final static int INTEGER = Types.INTEGER;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code BIGINT}.
*
* @see Types#BIGINT
*/
public final static int BIGINT = Types.BIGINT;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code FLOAT}.
*
* @see Types#FLOAT
*/
public final static int FLOAT = Types.FLOAT;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code REAL}.
*
* @see Types#REAL
*/
public final static int REAL = Types.REAL;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code DOUBLE}.
*
* @see Types#DOUBLE
*/
public final static int DOUBLE = Types.DOUBLE;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code NUMERIC}.
*
* @see Types#NUMERIC
*/
public final static int NUMERIC = Types.NUMERIC;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code DECIMAL}.
*
* @see Types#DECIMAL
*/
public final static int DECIMAL = Types.DECIMAL;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code CHAR}.
*
* @see Types#CHAR
*/
public final static int CHAR = Types.CHAR;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code VARCHAR}.
*
* @see Types#VARCHAR
*/
public final static int VARCHAR = Types.VARCHAR;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code LONGVARCHAR}.
*
* @see Types#LONGVARCHAR
*/
public final static int LONGVARCHAR = Types.LONGVARCHAR;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code DATE}.
*
* @see Types#DATE
*/
public final static int DATE = Types.DATE;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code TIME}.
*
* @see Types#TIME
*/
public final static int TIME = Types.TIME;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code TIMESTAMP}.
*
* @see Types#TIMESTAMP
*/
public final static int TIMESTAMP = Types.TIMESTAMP;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code BINARY}.
*
* @see Types#BINARY
*/
public final static int BINARY = Types.BINARY;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code VARBINARY}.
*
* @see Types#VARBINARY
*/
public final static int VARBINARY = Types.VARBINARY;
/**
* <P>The constant in the Java programming language, sometimes referred
* to as a type code, that identifies the generic SQL type
* {@code LONGVARBINARY}.
*
* @see Types#LONGVARBINARY
*/
public final static int LONGVARBINARY = Types.LONGVARBINARY;
/**
* <P>The constant in the Java programming language
* that identifies the generic SQL value
* {@code NULL}.
*
* @see Types#NULL
*/
public final static int NULL = Types.NULL;
/**
* The constant in the Java programming language that indicates
* that the SQL type is database-specific and
* gets mapped to a Java object that can be accessed via
* the methods {@code getObject} and {@code setObject}.
*
* @see Types#OTHER
*/
public final static int OTHER = Types.OTHER;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type
* {@code JAVA_OBJECT}.
*
* @see Types#JAVA_OBJECT
*/
public final static int JAVA_OBJECT = Types.JAVA_OBJECT;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type
* {@code DISTINCT}.
*
* @see Types#DISTINCT
*/
public final static int DISTINCT = Types.DISTINCT;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type
* {@code STRUCT}.
*
* @see Types#STRUCT
*/
public final static int STRUCT = Types.STRUCT;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type
* {@code ARRAY}.
*
* @see Types#ARRAY
*/
public final static int ARRAY = Types.ARRAY;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type
* {@code BLOB}.
*
* @see Types#ARRAY
*/
public final static int BLOB = Types.BLOB;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type
* {@code CLOB}.
*
* @see Types#CLOB
*/
public final static int CLOB = Types.CLOB;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type
* {@code REF}.
*
* @see Types#REF
*/
public final static int REF = Types.REF;
/**
* The constant in the Java programming language, somtimes referred to
* as a type code, that identifies the generic SQL type {@code DATALINK}.
*
* @see Types#DATALINK
*/
public final static int DATALINK = Types.DATALINK;
/**
* The constant in the Java programming language, somtimes referred to
* as a type code, that identifies the generic SQL type {@code BOOLEAN}.
*
* @see Types#BOOLEAN
*/
public final static int BOOLEAN = Types.BOOLEAN;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type {@code ROWID}
*
* @see Types#ROWID
*/
public final static int ROWID = Types.ROWID;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type {@code NCHAR}
*
* @see Types#NCHAR
*/
public static final int NCHAR = Types.NCHAR;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type {@code NVARCHAR}.
*
* @see Types#NVARCHAR
*/
public static final int NVARCHAR = Types.NVARCHAR;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type {@code LONGNVARCHAR}.
*
* @see Types#LONGNVARCHAR
*/
public static final int LONGNVARCHAR = Types.LONGNVARCHAR;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type {@code NCLOB}.
*
* @see Types#NCLOB
*/
public static final int NCLOB = Types.NCLOB;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type {@code XML}.
*
* @see Types#SQLXML
*/
public static final int SQLXML = Types.SQLXML;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type {@code REF CURSOR}.
*
* @see Types#REF_CURSOR
*/
public static final int REF_CURSOR = Types.REF_CURSOR;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type
* {@code TIME WITH TIMEZONE}.
*
* @see Types#TIME_WITH_TIMEZONE
*/
public static final int TIME_WITH_TIMEZONE = Types.TIME_WITH_TIMEZONE;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type
* {@code TIMESTAMP WITH TIMEZONE}.
*
* @see Types#TIMESTAMP_WITH_TIMEZONE
*/
public static final int TIMESTAMP_WITH_TIMEZONE = Types.TIMESTAMP_WITH_TIMEZONE;
// Misc types
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type
* {@code UUID}.
*/
public static final int UUID = 3000;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type
* {@code JSON}.
*/
public static final int JSON = 3001;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type
* {@code INET} for IPv4 or IPv6 addresses.
*/
public static final int INET = 3002;
// Interval types
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type
* {@code INTERVAL SECOND} for a temporal amount in terms of seconds and fractional seconds.
*/
public static final int INTERVAL_SECOND = 3100;
// Geometry types
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type
* {@code GEOMETRY}.
*/
public static final int GEOMETRY = 3200;
/**
* The constant in the Java programming language, sometimes referred to
* as a type code, that identifies the generic SQL type
* {@code POINT}.
*/
public static final int POINT = 3201;
private SqlTypes() {
}
}

Some files were not shown because too many files have changed in this diff Show More