Add SqlTypes.TIMESTAMP_UTC to as jdbc type for java.time.Instant
This commit is contained in:
parent
964e72f536
commit
af9edd50d6
|
@ -15,6 +15,7 @@ import org.hibernate.metamodel.mapping.JdbcMapping;
|
|||
import org.hibernate.metamodel.mapping.internal.BasicAttributeMapping;
|
||||
import org.hibernate.metamodel.spi.MappingMetamodelImplementor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
|
@ -41,7 +42,13 @@ public class InstantMappingTests {
|
|||
final BasicAttributeMapping duration = (BasicAttributeMapping) entityDescriptor.findAttributeMapping("instant");
|
||||
final JdbcMapping jdbcMapping = duration.getJdbcMapping();
|
||||
assertThat(jdbcMapping.getJavaTypeDescriptor().getJavaTypeClass(), equalTo(Instant.class));
|
||||
assertThat( jdbcMapping.getJdbcType().getJdbcTypeCode(), equalTo( Types.TIMESTAMP));
|
||||
assertThat(
|
||||
jdbcMapping.getJdbcType(),
|
||||
equalTo(
|
||||
mappingMetamodel.getTypeConfiguration().getJdbcTypeRegistry()
|
||||
.getDescriptor( SqlTypes.TIMESTAMP_UTC )
|
||||
)
|
||||
);
|
||||
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
|
|
|
@ -44,6 +44,7 @@ import org.hibernate.sql.exec.spi.JdbcOperation;
|
|||
import org.hibernate.type.BasicType;
|
||||
import org.hibernate.type.BasicTypeRegistry;
|
||||
import org.hibernate.type.StandardBasicTypes;
|
||||
import org.hibernate.type.descriptor.jdbc.InstantAsTimestampWithTimeZoneJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.UUIDJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
|
@ -113,6 +114,9 @@ public class CockroachDialect extends Dialect {
|
|||
return "bytes($l)";
|
||||
case BLOB:
|
||||
return "bytes";
|
||||
|
||||
case TIMESTAMP_UTC:
|
||||
return columnType( TIMESTAMP_WITH_TIMEZONE );
|
||||
}
|
||||
return super.columnType( sqlTypeCode );
|
||||
}
|
||||
|
@ -188,6 +192,7 @@ public class CockroachDialect extends Dialect {
|
|||
|
||||
final JdbcTypeRegistry jdbcTypeRegistry = typeContributions.getTypeConfiguration()
|
||||
.getJdbcTypeRegistry();
|
||||
jdbcTypeRegistry.addDescriptor( TIMESTAMP_UTC, InstantAsTimestampWithTimeZoneJdbcType.INSTANCE );
|
||||
if ( driverKind == PostgreSQLDriverKind.PG_JDBC ) {
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLIntervalSecondJdbcType.INSTANCE );
|
||||
|
|
|
@ -149,6 +149,8 @@ import org.hibernate.type.StandardBasicTypes;
|
|||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.ClobJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.InstantAsTimestampJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.InstantAsTimestampWithTimeZoneJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.LongNVarcharJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.NCharJdbcType;
|
||||
|
@ -306,6 +308,7 @@ public abstract class Dialect implements ConversionContext {
|
|||
ddlTypeRegistry.addDescriptor( simpleSqlType( TIME_WITH_TIMEZONE ) );
|
||||
ddlTypeRegistry.addDescriptor( simpleSqlType( TIMESTAMP ) );
|
||||
ddlTypeRegistry.addDescriptor( simpleSqlType( TIMESTAMP_WITH_TIMEZONE ) );
|
||||
ddlTypeRegistry.addDescriptor( simpleSqlType( TIMESTAMP_UTC ) );
|
||||
|
||||
ddlTypeRegistry.addDescriptor( simpleSqlType( CHAR ) );
|
||||
ddlTypeRegistry.addDescriptor(
|
||||
|
@ -410,6 +413,10 @@ public abstract class Dialect implements ConversionContext {
|
|||
return "timestamp($p)";
|
||||
case TIMESTAMP_WITH_TIMEZONE:
|
||||
return "timestamp($p) with time zone";
|
||||
case TIMESTAMP_UTC:
|
||||
return getTimeZoneSupport() == TimeZoneSupport.NATIVE
|
||||
? columnType( TIMESTAMP_WITH_TIMEZONE )
|
||||
: columnType( TIMESTAMP );
|
||||
|
||||
case CHAR:
|
||||
return "char($l)";
|
||||
|
@ -893,7 +900,7 @@ public abstract class Dialect implements ConversionContext {
|
|||
"instant",
|
||||
new CurrentFunction(
|
||||
"instant",
|
||||
currentTimestamp(),
|
||||
currentTimestampWithTimeZone(),
|
||||
instantType
|
||||
)
|
||||
);
|
||||
|
@ -1241,6 +1248,13 @@ public abstract class Dialect implements ConversionContext {
|
|||
ClobJdbcType.STREAM_BINDING
|
||||
);
|
||||
}
|
||||
|
||||
if ( getTimeZoneSupport() == TimeZoneSupport.NATIVE ) {
|
||||
typeContributions.contributeJdbcType( InstantAsTimestampWithTimeZoneJdbcType.INSTANCE );
|
||||
}
|
||||
else {
|
||||
typeContributions.contributeJdbcType( InstantAsTimestampJdbcType.INSTANCE );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3609,25 +3623,25 @@ public abstract class Dialect implements ConversionContext {
|
|||
}
|
||||
|
||||
switch ( jdbcTypeCode ) {
|
||||
case Types.BIT:
|
||||
case Types.CHAR:
|
||||
case Types.NCHAR:
|
||||
case Types.VARCHAR:
|
||||
case Types.NVARCHAR:
|
||||
case Types.BINARY:
|
||||
case Types.VARBINARY:
|
||||
case Types.CLOB:
|
||||
case Types.BLOB:
|
||||
case SqlTypes.BIT:
|
||||
case SqlTypes.CHAR:
|
||||
case SqlTypes.NCHAR:
|
||||
case SqlTypes.VARCHAR:
|
||||
case SqlTypes.NVARCHAR:
|
||||
case SqlTypes.BINARY:
|
||||
case SqlTypes.VARBINARY:
|
||||
case SqlTypes.CLOB:
|
||||
case SqlTypes.BLOB:
|
||||
size.setLength( javaType.getDefaultSqlLength( Dialect.this, jdbcType ) );
|
||||
break;
|
||||
case Types.LONGVARCHAR:
|
||||
case Types.LONGNVARCHAR:
|
||||
case Types.LONGVARBINARY:
|
||||
case SqlTypes.LONGVARCHAR:
|
||||
case SqlTypes.LONGNVARCHAR:
|
||||
case SqlTypes.LONGVARBINARY:
|
||||
size.setLength( javaType.getLongSqlLength() );
|
||||
break;
|
||||
case Types.FLOAT:
|
||||
case Types.DOUBLE:
|
||||
case Types.REAL:
|
||||
case SqlTypes.FLOAT:
|
||||
case SqlTypes.DOUBLE:
|
||||
case SqlTypes.REAL:
|
||||
// this is almost always the thing we use:
|
||||
size.setPrecision( javaType.getDefaultSqlPrecision( Dialect.this, jdbcType ) );
|
||||
if ( scale != null && scale != 0 ) {
|
||||
|
@ -3640,15 +3654,16 @@ public abstract class Dialect implements ConversionContext {
|
|||
precision = (int) ceil( precision * LOG_BASE2OF10 );
|
||||
}
|
||||
break;
|
||||
case Types.TIMESTAMP:
|
||||
case Types.TIMESTAMP_WITH_TIMEZONE:
|
||||
case SqlTypes.TIMESTAMP:
|
||||
case SqlTypes.TIMESTAMP_WITH_TIMEZONE:
|
||||
case SqlTypes.TIMESTAMP_UTC:
|
||||
size.setPrecision( javaType.getDefaultSqlPrecision( Dialect.this, jdbcType ) );
|
||||
if ( scale != null && scale != 0 ) {
|
||||
throw new IllegalArgumentException("scale has no meaning for timestamps");
|
||||
}
|
||||
break;
|
||||
case Types.NUMERIC:
|
||||
case Types.DECIMAL:
|
||||
case SqlTypes.NUMERIC:
|
||||
case SqlTypes.DECIMAL:
|
||||
case SqlTypes.INTERVAL_SECOND:
|
||||
size.setPrecision( javaType.getDefaultSqlPrecision( Dialect.this, jdbcType ) );
|
||||
break;
|
||||
|
|
|
@ -58,6 +58,7 @@ 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.descriptor.jdbc.InstantJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.UUIDJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.spi.JdbcTypeRegistry;
|
||||
|
@ -84,6 +85,7 @@ import static org.hibernate.type.SqlTypes.NVARCHAR;
|
|||
import static org.hibernate.type.SqlTypes.UUID;
|
||||
import static org.hibernate.type.SqlTypes.VARBINARY;
|
||||
import static org.hibernate.type.SqlTypes.VARCHAR;
|
||||
import static org.hibernate.type.SqlTypes.TIMESTAMP_UTC;
|
||||
|
||||
/**
|
||||
* A {@linkplain Dialect SQL dialect} for H2.
|
||||
|
@ -228,6 +230,7 @@ public class H2Dialect extends Dialect {
|
|||
final JdbcTypeRegistry jdbcTypeRegistry = typeContributions.getTypeConfiguration()
|
||||
.getJdbcTypeRegistry();
|
||||
|
||||
jdbcTypeRegistry.addDescriptor( TIMESTAMP_UTC, InstantJdbcType.INSTANCE );
|
||||
if ( getVersion().isSameOrAfter( 1, 4, 197 ) ) {
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( UUIDJdbcType.INSTANCE );
|
||||
}
|
||||
|
|
|
@ -1014,12 +1014,6 @@ public class MySQLDialect extends Dialect {
|
|||
return getMySQLVersion().isBefore( 5, 5 ) ? MyISAMStorageEngine.INSTANCE : InnoDBStorageEngine.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimeZoneSupport getTimeZoneSupport() {
|
||||
// In MySQL and MariaDB, the TIMESTAMP type normalize to UTC just like PostgreSQL
|
||||
return TimeZoneSupport.NORMALIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendLiteral(SqlAppender appender, String literal) {
|
||||
appender.appendSql( '\'' );
|
||||
|
|
|
@ -67,6 +67,7 @@ import org.hibernate.type.JavaObjectType;
|
|||
import org.hibernate.type.descriptor.java.PrimitiveByteArrayJavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.BlobJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.ClobJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.InstantAsTimestampWithTimeZoneJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.ObjectNullAsBinaryTypeJdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.UUIDJdbcType;
|
||||
|
@ -154,6 +155,9 @@ public class PostgreSQLDialect extends Dialect {
|
|||
case VARBINARY:
|
||||
case LONG32VARBINARY:
|
||||
return "bytea";
|
||||
|
||||
case TIMESTAMP_UTC:
|
||||
return columnType( TIMESTAMP_WITH_TIMEZONE );
|
||||
}
|
||||
return super.columnType( sqlTypeCode );
|
||||
}
|
||||
|
@ -1065,6 +1069,7 @@ public class PostgreSQLDialect extends Dialect {
|
|||
// dialect uses oid for Blobs, byte arrays cannot be used.
|
||||
jdbcTypeRegistry.addDescriptor( Types.BLOB, BlobJdbcType.BLOB_BINDING );
|
||||
jdbcTypeRegistry.addDescriptor( Types.CLOB, ClobJdbcType.CLOB_BINDING );
|
||||
jdbcTypeRegistry.addDescriptor( TIMESTAMP_UTC, InstantAsTimestampWithTimeZoneJdbcType.INSTANCE );
|
||||
|
||||
if ( driverKind == PostgreSQLDriverKind.PG_JDBC ) {
|
||||
jdbcTypeRegistry.addDescriptorIfAbsent( PostgreSQLInetJdbcType.INSTANCE );
|
||||
|
|
|
@ -71,7 +71,7 @@ public class Replacer {
|
|||
for ( Replacement replacement : replacements ) {
|
||||
int result = replacement.apply( chunk, position );
|
||||
if ( result >= 0 ) {
|
||||
position += result;
|
||||
position += result - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -437,7 +437,7 @@ public class SpannerDialect extends Dialect {
|
|||
|
||||
queryEngine.getSqmFunctionRegistry().register(
|
||||
"format",
|
||||
new FormatFunction( "format_timestamp", true, queryEngine.getTypeConfiguration() )
|
||||
new FormatFunction( "format_timestamp", true, true, queryEngine.getTypeConfiguration() )
|
||||
);
|
||||
functionFactory.listagg_stringAgg( "string" );
|
||||
functionFactory.inverseDistributionOrderedSetAggregates();
|
||||
|
|
|
@ -9,6 +9,14 @@ package org.hibernate.dialect.function;
|
|||
import java.util.List;
|
||||
|
||||
import org.hibernate.dialect.OracleDialect;
|
||||
import org.hibernate.query.ReturnableType;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
import org.hibernate.query.sqm.function.FunctionRenderingSupport;
|
||||
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
|
||||
import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
|
||||
import org.hibernate.query.sqm.produce.function.FunctionReturnTypeResolver;
|
||||
import org.hibernate.query.sqm.tree.SqmTypedNode;
|
||||
import org.hibernate.sql.ast.SqlAstTranslator;
|
||||
import org.hibernate.sql.ast.spi.SqlAppender;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
@ -26,12 +34,13 @@ import jakarta.persistence.TemporalType;
|
|||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class DB2FormatEmulation
|
||||
extends FormatFunction {
|
||||
public class DB2FormatEmulation extends FormatFunction {
|
||||
|
||||
public DB2FormatEmulation(TypeConfiguration typeConfiguration) {
|
||||
super(
|
||||
"format",
|
||||
"varchar_format",
|
||||
false,
|
||||
false,
|
||||
typeConfiguration
|
||||
);
|
||||
}
|
||||
|
@ -41,47 +50,19 @@ public class DB2FormatEmulation
|
|||
SqlAppender sqlAppender,
|
||||
List<? extends SqlAstNode> arguments,
|
||||
SqlAstTranslator<?> walker) {
|
||||
final Expression datetime = (Expression) arguments.get(0);
|
||||
final boolean isTime = TypeConfiguration.getSqlTemporalType( datetime.getExpressionType() ) == TemporalType.TIME;
|
||||
final Format format = (Format) arguments.get(1);
|
||||
|
||||
sqlAppender.appendSql("(");
|
||||
String[] bits = OracleDialect.datetimeFormat( format.getFormat(), false, false ).result().split("\"");
|
||||
boolean first = true;
|
||||
for ( int i=0; i<bits.length; i++ ) {
|
||||
String bit = bits[i];
|
||||
if ( !bit.isEmpty() ) {
|
||||
if ( first ) {
|
||||
first = false;
|
||||
}
|
||||
else {
|
||||
sqlAppender.appendSql("||");
|
||||
}
|
||||
if ( i % 2 == 0 ) {
|
||||
sqlAppender.appendSql("varchar_format(");
|
||||
// Times need to be wrapped into a timestamp to be able to use formatting
|
||||
if ( isTime ) {
|
||||
sqlAppender.appendSql( "timestamp(current_date," );
|
||||
datetime.accept( walker );
|
||||
sqlAppender.appendSql( ")" );
|
||||
}
|
||||
else {
|
||||
datetime.accept( walker );
|
||||
}
|
||||
sqlAppender.appendSql(",'");
|
||||
sqlAppender.appendSql( bit );
|
||||
sqlAppender.appendSql("')");
|
||||
}
|
||||
else {
|
||||
sqlAppender.appendSql("'");
|
||||
sqlAppender.appendSql( bit );
|
||||
sqlAppender.appendSql("'");
|
||||
}
|
||||
}
|
||||
final Expression datetime = (Expression) arguments.get( 0 );
|
||||
sqlAppender.appendSql( "varchar_format(" );
|
||||
// Times need to be wrapped into a timestamp to be able to use formatting
|
||||
if ( TypeConfiguration.getSqlTemporalType( datetime.getExpressionType() ) == TemporalType.TIME ) {
|
||||
sqlAppender.appendSql( "timestamp(current_date," );
|
||||
datetime.accept( walker );
|
||||
sqlAppender.appendSql( ")" );
|
||||
}
|
||||
if ( first ) {
|
||||
sqlAppender.appendSql("''");
|
||||
else {
|
||||
datetime.accept( walker );
|
||||
}
|
||||
sqlAppender.appendSql(")");
|
||||
sqlAppender.appendSql( "," );
|
||||
arguments.get( 1 ).accept( walker );
|
||||
sqlAppender.appendSql( ")" );
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -18,7 +18,7 @@ import org.hibernate.sql.ast.tree.SqlAstNode;
|
|||
* @author Gavin King
|
||||
*/
|
||||
public class Format implements SqlExpressible, SqlAstNode {
|
||||
private String format;
|
||||
private final String format;
|
||||
|
||||
public Format(String format) {
|
||||
this.format = format;
|
||||
|
|
|
@ -425,6 +425,13 @@ public class SqlTypes {
|
|||
*/
|
||||
public static final int INET = 3002;
|
||||
|
||||
/**
|
||||
* The constant in the Java programming language, sometimes referred to
|
||||
* as a type code, that identifies the generic SQL type
|
||||
* {@code TIMESTAMP_UTC}.
|
||||
*/
|
||||
public static final int TIMESTAMP_UTC = 3003;
|
||||
|
||||
// Interval types
|
||||
|
||||
/**
|
||||
|
|
|
@ -458,7 +458,7 @@ public final class StandardBasicTypes {
|
|||
public static final BasicTypeReference<Instant> INSTANT = new BasicTypeReference<>(
|
||||
"instant",
|
||||
Instant.class,
|
||||
SqlTypes.TIMESTAMP
|
||||
SqlTypes.TIMESTAMP_UTC
|
||||
);
|
||||
|
||||
/**
|
||||
|
|
|
@ -22,6 +22,7 @@ import jakarta.persistence.TemporalType;
|
|||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcType;
|
||||
import org.hibernate.type.descriptor.jdbc.JdbcTypeIndicators;
|
||||
|
@ -68,7 +69,7 @@ public class InstantJavaType extends AbstractTemporalJavaType<Instant>
|
|||
|
||||
@Override
|
||||
public JdbcType getRecommendedJdbcType(JdbcTypeIndicators context) {
|
||||
return context.getTypeConfiguration().getJdbcTypeRegistry().getDescriptor( Types.TIMESTAMP );
|
||||
return context.getTypeConfiguration().getJdbcTypeRegistry().getDescriptor( SqlTypes.TIMESTAMP_UTC );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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.descriptor.jdbc;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
import java.time.Instant;
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
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.BasicJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.internal.JdbcLiteralFormatterTemporal;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link SqlTypes#TIMESTAMP_UTC TIMESTAMP_UTC} handling.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class InstantAsTimestampJdbcType implements JdbcType {
|
||||
|
||||
public static final InstantAsTimestampJdbcType INSTANCE = new InstantAsTimestampJdbcType();
|
||||
private static final Calendar UTC_CALENDAR = Calendar.getInstance( TimeZone.getTimeZone( "UTC" ) );
|
||||
|
||||
public InstantAsTimestampJdbcType() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getJdbcTypeCode() {
|
||||
return Types.TIMESTAMP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultSqlTypeCode() {
|
||||
return SqlTypes.TIMESTAMP_UTC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFriendlyName() {
|
||||
return "TIMESTAMP_UTC";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TimestampUtcDescriptor";
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaType<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaType<T>) typeConfiguration.getJavaTypeRegistry().getDescriptor( Instant.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaType) {
|
||||
return new JdbcLiteralFormatterTemporal<>( javaType, TemporalType.TIMESTAMP );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(final JavaType<X> javaType) {
|
||||
return new BasicBinder<>( javaType, this ) {
|
||||
@Override
|
||||
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
|
||||
final Instant instant = javaType.unwrap( value, Instant.class, options );
|
||||
st.setTimestamp( index, Timestamp.from( instant ), UTC_CALENDAR );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
|
||||
throws SQLException {
|
||||
final Instant instant = javaType.unwrap( value, Instant.class, options );
|
||||
st.setTimestamp( name, Timestamp.from( instant ), UTC_CALENDAR );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(final JavaType<X> javaType) {
|
||||
return new BasicExtractor<>( javaType, this ) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, int paramIndex, WrapperOptions options) throws SQLException {
|
||||
final Timestamp timestamp = rs.getTimestamp( paramIndex, UTC_CALENDAR );
|
||||
return javaType.wrap( timestamp == null ? null : timestamp.toInstant(), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
final Timestamp timestamp = statement.getTimestamp( index, UTC_CALENDAR );
|
||||
return javaType.wrap( timestamp == null ? null : timestamp.toInstant(), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
final Timestamp timestamp = statement.getTimestamp( name, UTC_CALENDAR );
|
||||
return javaType.wrap( timestamp == null ? null : timestamp.toInstant(), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* 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.descriptor.jdbc;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
import java.time.Instant;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
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.BasicJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.internal.JdbcLiteralFormatterTemporal;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link SqlTypes#TIMESTAMP_UTC TIMESTAMP_UTC} handling.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class InstantAsTimestampWithTimeZoneJdbcType implements JdbcType {
|
||||
|
||||
public static final InstantAsTimestampWithTimeZoneJdbcType INSTANCE = new InstantAsTimestampWithTimeZoneJdbcType();
|
||||
|
||||
public InstantAsTimestampWithTimeZoneJdbcType() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getJdbcTypeCode() {
|
||||
return Types.TIMESTAMP_WITH_TIMEZONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultSqlTypeCode() {
|
||||
return SqlTypes.TIMESTAMP_UTC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFriendlyName() {
|
||||
return "TIMESTAMP_UTC";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TimestampUtcDescriptor";
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaType<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaType<T>) typeConfiguration.getJavaTypeRegistry().getDescriptor( Instant.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaType) {
|
||||
return new JdbcLiteralFormatterTemporal<>( javaType, TemporalType.TIMESTAMP );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(final JavaType<X> javaType) {
|
||||
return new BasicBinder<>( javaType, this ) {
|
||||
@Override
|
||||
protected void doBind(
|
||||
PreparedStatement st,
|
||||
X value,
|
||||
int index,
|
||||
WrapperOptions wrapperOptions) throws SQLException {
|
||||
final OffsetDateTime dateTime = javaType.unwrap( value, OffsetDateTime.class, wrapperOptions );
|
||||
// supposed to be supported in JDBC 4.2
|
||||
st.setObject( index, dateTime, Types.TIMESTAMP_WITH_TIMEZONE );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(
|
||||
CallableStatement st,
|
||||
X value,
|
||||
String name,
|
||||
WrapperOptions wrapperOptions)
|
||||
throws SQLException {
|
||||
final OffsetDateTime dateTime = javaType.unwrap( value, OffsetDateTime.class, wrapperOptions );
|
||||
// supposed to be supported in JDBC 4.2
|
||||
st.setObject( name, dateTime, Types.TIMESTAMP_WITH_TIMEZONE );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(final JavaType<X> javaType) {
|
||||
return new BasicExtractor<>( javaType, this ) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, int position, WrapperOptions wrapperOptions) throws SQLException {
|
||||
return javaType.wrap( rs.getObject( position, OffsetDateTime.class ), wrapperOptions );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, int position, WrapperOptions wrapperOptions) throws SQLException {
|
||||
return javaType.wrap( statement.getObject( position, OffsetDateTime.class ), wrapperOptions );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions wrapperOptions) throws SQLException {
|
||||
return javaType.wrap( statement.getObject( name, OffsetDateTime.class ), wrapperOptions );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* 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.descriptor.jdbc;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
import java.time.Instant;
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
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.BasicJavaType;
|
||||
import org.hibernate.type.descriptor.java.JavaType;
|
||||
import org.hibernate.type.descriptor.jdbc.internal.JdbcLiteralFormatterTemporal;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import jakarta.persistence.TemporalType;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link SqlTypes#TIMESTAMP_UTC TIMESTAMP_UTC} handling.
|
||||
*
|
||||
* @author Christian Beikov
|
||||
*/
|
||||
public class InstantJdbcType implements JdbcType {
|
||||
public static final InstantJdbcType INSTANCE = new InstantJdbcType();
|
||||
|
||||
public InstantJdbcType() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getJdbcTypeCode() {
|
||||
return Types.TIMESTAMP_WITH_TIMEZONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDefaultSqlTypeCode() {
|
||||
return SqlTypes.TIMESTAMP_UTC;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFriendlyName() {
|
||||
return "TIMESTAMP_UTC";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TimestampUtcDescriptor";
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaType<T> getJdbcRecommendedJavaTypeMapping(
|
||||
Integer length,
|
||||
Integer scale,
|
||||
TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaType<T>) typeConfiguration.getJavaTypeRegistry().getDescriptor( Instant.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaType<T> javaType) {
|
||||
return new JdbcLiteralFormatterTemporal<>( javaType, TemporalType.TIMESTAMP );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(final JavaType<X> javaType) {
|
||||
return new BasicBinder<>( javaType, this ) {
|
||||
@Override
|
||||
protected void doBind(
|
||||
PreparedStatement st,
|
||||
X value,
|
||||
int index,
|
||||
WrapperOptions wrapperOptions) throws SQLException {
|
||||
try {
|
||||
final Instant dateTime = javaType.unwrap( value, Instant.class, wrapperOptions );
|
||||
// supposed to be supported in JDBC 4.2
|
||||
st.setObject( index, dateTime, Types.TIMESTAMP_WITH_TIMEZONE );
|
||||
}
|
||||
catch (SQLException|AbstractMethodError e) {
|
||||
// fall back to treating it as a JDBC Timestamp
|
||||
final Timestamp timestamp = javaType.unwrap( value, Timestamp.class, wrapperOptions );
|
||||
st.setTimestamp( index, timestamp );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(
|
||||
CallableStatement st,
|
||||
X value,
|
||||
String name,
|
||||
WrapperOptions wrapperOptions)
|
||||
throws SQLException {
|
||||
try {
|
||||
final Instant dateTime = javaType.unwrap( value, Instant.class, wrapperOptions );
|
||||
// supposed to be supported in JDBC 4.2
|
||||
st.setObject( name, dateTime, Types.TIMESTAMP_WITH_TIMEZONE );
|
||||
}
|
||||
catch (SQLException|AbstractMethodError e) {
|
||||
// fall back to treating it as a JDBC Timestamp
|
||||
final Timestamp timestamp = javaType.unwrap( value, Timestamp.class, wrapperOptions );
|
||||
st.setTimestamp( name, timestamp );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(final JavaType<X> javaType) {
|
||||
return new BasicExtractor<>( javaType, this ) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, int position, WrapperOptions wrapperOptions) throws SQLException {
|
||||
try {
|
||||
// supposed to be supported in JDBC 4.2
|
||||
return javaType.wrap( rs.getObject( position, Instant.class ), wrapperOptions );
|
||||
}
|
||||
catch (SQLException|AbstractMethodError e) {
|
||||
// fall back to treating it as a JDBC Timestamp
|
||||
return javaType.wrap( rs.getTimestamp( position ), wrapperOptions );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, int position, WrapperOptions wrapperOptions) throws SQLException {
|
||||
try {
|
||||
// supposed to be supported in JDBC 4.2
|
||||
return javaType.wrap( statement.getObject( position, Instant.class ), wrapperOptions );
|
||||
}
|
||||
catch (SQLException|AbstractMethodError e) {
|
||||
// fall back to treating it as a JDBC Timestamp
|
||||
return javaType.wrap( statement.getTimestamp( position ), wrapperOptions );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions wrapperOptions) throws SQLException {
|
||||
try {
|
||||
// supposed to be supported in JDBC 4.2
|
||||
return javaType.wrap( statement.getObject( name, Instant.class ), wrapperOptions );
|
||||
}
|
||||
catch (SQLException|AbstractMethodError e) {
|
||||
// fall back to treating it as a JDBC Timestamp
|
||||
return javaType.wrap( statement.getTimestamp( name ), wrapperOptions );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -21,6 +21,7 @@ import java.sql.Struct;
|
|||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
|
@ -127,6 +128,7 @@ public class JdbcTypeJavaClassMappings {
|
|||
workMap.put( LocalDateTime.class, SqlTypes.TIMESTAMP );
|
||||
workMap.put( OffsetDateTime.class, SqlTypes.TIMESTAMP_WITH_TIMEZONE );
|
||||
workMap.put( ZonedDateTime.class, SqlTypes.TIMESTAMP_WITH_TIMEZONE );
|
||||
workMap.put( Instant.class, SqlTypes.TIMESTAMP_UTC );
|
||||
workMap.put( Blob.class, SqlTypes.BLOB );
|
||||
workMap.put( Clob.class, SqlTypes.CLOB );
|
||||
workMap.put( Array.class, SqlTypes.ARRAY );
|
||||
|
@ -190,6 +192,7 @@ public class JdbcTypeJavaClassMappings {
|
|||
workMap.put( SqlTypes.SQLXML, SQLXML.class );
|
||||
workMap.put( SqlTypes.UUID, UUID.class );
|
||||
workMap.put( SqlTypes.INET, InetAddress.class );
|
||||
workMap.put( SqlTypes.TIMESTAMP_UTC, Instant.class );
|
||||
workMap.put( SqlTypes.INTERVAL_SECOND, Duration.class );
|
||||
|
||||
return workMap;
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.util.Map;
|
|||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.Size;
|
||||
import org.hibernate.type.SqlTypes;
|
||||
import org.hibernate.type.descriptor.sql.DdlType;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
|
@ -78,12 +79,12 @@ public class DdlTypeRegistry implements Serializable {
|
|||
// they're just used to indicate that JavaType.getLongSqlLength()
|
||||
// should be used by default (and that's already handled by the
|
||||
// time we get to here)
|
||||
case Types.LONGVARCHAR:
|
||||
return ddlTypes.get( Types.VARCHAR );
|
||||
case Types.LONGNVARCHAR:
|
||||
return ddlTypes.get( Types.NVARCHAR );
|
||||
case Types.LONGVARBINARY:
|
||||
return ddlTypes.get( Types.VARBINARY );
|
||||
case SqlTypes.LONGVARCHAR:
|
||||
return ddlTypes.get( SqlTypes.VARCHAR );
|
||||
case SqlTypes.LONGNVARCHAR:
|
||||
return ddlTypes.get( SqlTypes.NVARCHAR );
|
||||
case SqlTypes.LONGVARBINARY:
|
||||
return ddlTypes.get( SqlTypes.VARBINARY );
|
||||
}
|
||||
}
|
||||
return ddlType;
|
||||
|
@ -92,16 +93,17 @@ public class DdlTypeRegistry implements Serializable {
|
|||
public String getTypeName(int typeCode, Dialect dialect) {
|
||||
// explicitly enforce dialect's default precisions
|
||||
switch ( typeCode ) {
|
||||
case Types.DECIMAL:
|
||||
case Types.NUMERIC:
|
||||
case SqlTypes.DECIMAL:
|
||||
case SqlTypes.NUMERIC:
|
||||
return getTypeName( typeCode, Size.precision( dialect.getDefaultDecimalPrecision() ) );
|
||||
case Types.FLOAT:
|
||||
case Types.REAL:
|
||||
case SqlTypes.FLOAT:
|
||||
case SqlTypes.REAL:
|
||||
return getTypeName( typeCode, Size.precision( dialect.getFloatPrecision() ) );
|
||||
case Types.DOUBLE:
|
||||
case SqlTypes.DOUBLE:
|
||||
return getTypeName( typeCode, Size.precision( dialect.getDoublePrecision() ) );
|
||||
case Types.TIMESTAMP:
|
||||
case Types.TIMESTAMP_WITH_TIMEZONE:
|
||||
case SqlTypes.TIMESTAMP:
|
||||
case SqlTypes.TIMESTAMP_WITH_TIMEZONE:
|
||||
case SqlTypes.TIMESTAMP_UTC:
|
||||
return getTypeName( typeCode, Size.precision( dialect.getDefaultTimestampPrecision() ) );
|
||||
default:
|
||||
return getTypeName( typeCode, Size.nil() );
|
||||
|
|
|
@ -354,7 +354,7 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
|
|||
|
||||
@Override
|
||||
public int getPreferredSqlTypeCodeForBoolean() {
|
||||
return Types.BOOLEAN;
|
||||
return SqlTypes.BOOLEAN;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -635,13 +635,14 @@ public class TypeConfiguration implements SessionFactoryObserver, Serializable {
|
|||
|
||||
protected static TemporalType getSqlTemporalType(int jdbcTypeCode) {
|
||||
switch ( jdbcTypeCode ) {
|
||||
case Types.TIMESTAMP:
|
||||
case Types.TIMESTAMP_WITH_TIMEZONE:
|
||||
case SqlTypes.TIMESTAMP:
|
||||
case SqlTypes.TIMESTAMP_WITH_TIMEZONE:
|
||||
case SqlTypes.TIMESTAMP_UTC:
|
||||
return TemporalType.TIMESTAMP;
|
||||
case Types.TIME:
|
||||
case Types.TIME_WITH_TIMEZONE:
|
||||
case SqlTypes.TIME:
|
||||
case SqlTypes.TIME_WITH_TIMEZONE:
|
||||
return TemporalType.TIME;
|
||||
case Types.DATE:
|
||||
case SqlTypes.DATE:
|
||||
return TemporalType.DATE;
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -16,7 +16,10 @@ import java.time.OffsetDateTime;
|
|||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import jakarta.persistence.Basic;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
|
@ -27,6 +30,7 @@ import org.hibernate.dialect.MariaDBDialect;
|
|||
import org.hibernate.dialect.MySQLDialect;
|
||||
import org.hibernate.dialect.SybaseASEDialect;
|
||||
import org.hibernate.dialect.SybaseDialect;
|
||||
import org.hibernate.dialect.TimeZoneSupport;
|
||||
|
||||
import org.junit.runners.Parameterized;
|
||||
|
||||
|
@ -149,25 +153,33 @@ public class InstantTest extends AbstractJavaTimeTypeTest<Instant, InstantTest.E
|
|||
|
||||
@Override
|
||||
protected void setJdbcValueForNonHibernateWrite(PreparedStatement statement, int parameterIndex) throws SQLException {
|
||||
statement.setTimestamp( parameterIndex, getExpectedJdbcValueAfterHibernateWrite() );
|
||||
if ( sessionFactory().getJdbcServices().getDialect().getTimeZoneSupport() == TimeZoneSupport.NATIVE ) {
|
||||
// Oracle and H2 require reading/writing through OffsetDateTime to avoid TZ related miscalculations
|
||||
statement.setObject( parameterIndex, getExpectedJdbcValueAfterHibernateWrite().toInstant().atOffset( ZoneOffset.UTC ) );
|
||||
}
|
||||
else {
|
||||
statement.setTimestamp(
|
||||
parameterIndex,
|
||||
getExpectedJdbcValueAfterHibernateWrite(),
|
||||
Calendar.getInstance( TimeZone.getTimeZone( "UTC" ) )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Timestamp getExpectedJdbcValueAfterHibernateWrite() {
|
||||
LocalDateTime dateTimeInDefaultTimeZone = getExpectedPropertyValueAfterHibernateRead().atZone( ZoneId.systemDefault() )
|
||||
.toLocalDateTime();
|
||||
return new Timestamp(
|
||||
dateTimeInDefaultTimeZone.getYear() - 1900, dateTimeInDefaultTimeZone.getMonthValue() - 1,
|
||||
dateTimeInDefaultTimeZone.getDayOfMonth(),
|
||||
dateTimeInDefaultTimeZone.getHour(), dateTimeInDefaultTimeZone.getMinute(),
|
||||
dateTimeInDefaultTimeZone.getSecond(),
|
||||
dateTimeInDefaultTimeZone.getNano()
|
||||
);
|
||||
return Timestamp.from( getExpectedPropertyValueAfterHibernateRead() );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getActualJdbcValue(ResultSet resultSet, int columnIndex) throws SQLException {
|
||||
return resultSet.getTimestamp( columnIndex );
|
||||
if ( sessionFactory().getJdbcServices().getDialect().getTimeZoneSupport() == TimeZoneSupport.NATIVE ) {
|
||||
// Oracle and H2 require reading/writing through OffsetDateTime to avoid TZ related miscalculations
|
||||
return Timestamp.from( resultSet.getObject( columnIndex, OffsetDateTime.class ).toInstant() );
|
||||
}
|
||||
else {
|
||||
return resultSet.getTimestamp( columnIndex, Calendar.getInstance( TimeZone.getTimeZone( "UTC" ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = ENTITY_NAME)
|
||||
|
|
Loading…
Reference in New Issue