mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-27 14:30:16 +00:00
Support for timezones
- add TimestampWithTimeZoneDescriptor and use it in OffsetDateTimeJD and ZonedDateTimeJD - add ZoneOffsetJavaDescriptor for ZoneOffset attributes - clean up string rendering for temporal types using ISO formats; note that they do not need to implement objectToSQLString() since they cannot be discriminators Note that at this time very few databases have meaningful support for the ANSI-standard TIMESTAMP WITH TIME ZONE type. This limits the usefulness of TimestampWithTimeZoneDescriptor for now. Also add in some missing but needed type mappings for temporal types
This commit is contained in:
parent
5a3838dfa6
commit
95930820af
@ -61,18 +61,6 @@ public Comparator<Date> getComparator() {
|
||||
return getJavaTypeDescriptor().getComparator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String objectToSQLString(
|
||||
Date value,
|
||||
Dialect dialect) throws Exception {
|
||||
final Timestamp ts = Timestamp.class.isInstance( value )
|
||||
? ( Timestamp ) value
|
||||
: new Timestamp( value.getTime() );
|
||||
return StringType.INSTANCE.objectToSQLString(
|
||||
ts.toString(), dialect
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date fromStringValue(
|
||||
String xml) throws HibernateException {
|
||||
|
@ -7,6 +7,8 @@
|
||||
package org.hibernate.type;
|
||||
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
|
||||
/**
|
||||
* Additional contract for a {@link Type} may be used for a discriminator.
|
||||
*
|
||||
@ -14,4 +16,15 @@
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface DiscriminatorType<T> extends IdentifierType<T>, LiteralType<T> {
|
||||
/**
|
||||
* Render the given discriminator value to a literal format
|
||||
* for embedding in the generated SQL.
|
||||
*
|
||||
* @param value The value to convert
|
||||
* @param dialect The SQL dialect
|
||||
*
|
||||
* @return The value's SQL literal representation
|
||||
*/
|
||||
@Override
|
||||
String objectToSQLString(T value, Dialect dialect) throws Exception;
|
||||
}
|
||||
|
@ -27,11 +27,6 @@ public DurationType() {
|
||||
super( BigIntTypeDescriptor.INSTANCE, DurationJavaDescriptor.INSTANCE );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String objectToSQLString(Duration value, Dialect dialect) throws Exception {
|
||||
return String.valueOf( value.toNanos() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return Duration.class.getSimpleName();
|
||||
|
@ -43,11 +43,6 @@ public InstantType() {
|
||||
super( TimestampTypeDescriptor.INSTANCE, InstantJavaDescriptor.INSTANCE );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String objectToSQLString(Instant value, Dialect dialect) throws Exception {
|
||||
return "{ts '" + FORMATTER.format( ZonedDateTime.ofInstant( value, ZoneId.of( "UTC" ) ) ) + "'}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Instant seed(SharedSessionContractImplementor session) {
|
||||
return Instant.now();
|
||||
|
@ -5,6 +5,7 @@
|
||||
* 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.AssertionFailure;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
|
||||
/**
|
||||
@ -29,6 +30,8 @@ public interface LiteralType<T> {
|
||||
*
|
||||
* @throws Exception Indicates an issue converting the value to literal string.
|
||||
*/
|
||||
public String objectToSQLString(T value, Dialect dialect) throws Exception;
|
||||
default String objectToSQLString(T value, Dialect dialect) throws Exception {
|
||||
throw new AssertionFailure("not a discriminator type");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Comparator;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
@ -35,8 +34,6 @@ public class LocalDateTimeType
|
||||
*/
|
||||
public static final LocalDateTimeType INSTANCE = new LocalDateTimeType();
|
||||
|
||||
public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss.S", Locale.ENGLISH );
|
||||
|
||||
public LocalDateTimeType() {
|
||||
super( TimestampTypeDescriptor.INSTANCE, LocalDateTimeJavaDescriptor.INSTANCE );
|
||||
}
|
||||
@ -51,11 +48,6 @@ protected boolean registerUnderJavaType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String objectToSQLString(LocalDateTime value, Dialect dialect) throws Exception {
|
||||
return "{ts '" + FORMATTER.format( value ) + "'}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime seed(SharedSessionContractImplementor session) {
|
||||
return LocalDateTime.now();
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Locale;
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.QueryException;
|
||||
@ -30,8 +29,6 @@ public class LocalDateType
|
||||
*/
|
||||
public static final LocalDateType INSTANCE = new LocalDateType();
|
||||
|
||||
public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern( "yyyy-MM-dd", Locale.ENGLISH );
|
||||
|
||||
public LocalDateType() {
|
||||
super( DateTypeDescriptor.INSTANCE, LocalDateJavaDescriptor.INSTANCE );
|
||||
}
|
||||
@ -46,11 +43,6 @@ protected boolean registerUnderJavaType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String objectToSQLString(LocalDate value, Dialect dialect) throws Exception {
|
||||
return "{d '" + FORMATTER.format( value ) + "'}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public AllowableTemporalParameterType resolveTemporalPrecision(
|
||||
TemporalType temporalPrecision,
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
@ -31,8 +30,6 @@ public class LocalTimeType
|
||||
*/
|
||||
public static final LocalTimeType INSTANCE = new LocalTimeType();
|
||||
|
||||
public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern( "HH:mm:ss", Locale.ENGLISH );
|
||||
|
||||
public LocalTimeType() {
|
||||
super( TimeTypeDescriptor.INSTANCE, LocalTimeJavaDescriptor.INSTANCE );
|
||||
}
|
||||
@ -47,11 +44,6 @@ protected boolean registerUnderJavaType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String objectToSQLString(LocalTime value, Dialect dialect) throws Exception {
|
||||
return "{t '" + FORMATTER.format( value ) + "'}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public AllowableTemporalParameterType resolveTemporalPrecision(
|
||||
TemporalType temporalPrecision,
|
||||
|
@ -7,18 +7,15 @@
|
||||
package org.hibernate.type;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Comparator;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.metamodel.model.domain.AllowableTemporalParameterType;
|
||||
import org.hibernate.type.descriptor.java.OffsetDateTimeJavaDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.TimestampTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.TimestampWithTimeZoneDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
@ -33,15 +30,8 @@ public class OffsetDateTimeType
|
||||
*/
|
||||
public static final OffsetDateTimeType INSTANCE = new OffsetDateTimeType();
|
||||
|
||||
public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss.S xxxxx", Locale.ENGLISH );
|
||||
|
||||
public OffsetDateTimeType() {
|
||||
super( TimestampTypeDescriptor.INSTANCE, OffsetDateTimeJavaDescriptor.INSTANCE );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String objectToSQLString(OffsetDateTime value, Dialect dialect) throws Exception {
|
||||
return "{ts '" + FORMATTER.format( value ) + "'}";
|
||||
super( TimestampWithTimeZoneDescriptor.INSTANCE, OffsetDateTimeJavaDescriptor.INSTANCE );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -8,7 +8,6 @@
|
||||
|
||||
import java.time.OffsetTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Locale;
|
||||
|
||||
import javax.persistence.TemporalType;
|
||||
|
||||
@ -31,17 +30,10 @@ public class OffsetTimeType
|
||||
*/
|
||||
public static final OffsetTimeType INSTANCE = new OffsetTimeType();
|
||||
|
||||
public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern( "HH:mm:ss.S xxxxx", Locale.ENGLISH );
|
||||
|
||||
public OffsetTimeType() {
|
||||
super( TimeTypeDescriptor.INSTANCE, OffsetTimeJavaDescriptor.INSTANCE );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String objectToSQLString(OffsetTime value, Dialect dialect) throws Exception {
|
||||
return "{t '" + FORMATTER.format( value ) + "'}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return OffsetTime.class.getSimpleName();
|
||||
|
@ -19,6 +19,7 @@
|
||||
import java.time.LocalTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.OffsetTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Currency;
|
||||
@ -463,6 +464,13 @@ private StandardBasicTypes() {
|
||||
*/
|
||||
public static final CurrencyType CURRENCY = CurrencyType.INSTANCE;
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.time.ZoneOffset} to JDBC {@link java.sql.Types#VARCHAR VARCHAR}.
|
||||
*
|
||||
* @see ZoneOffsetType
|
||||
*/
|
||||
public static final ZoneOffsetType ZONE_OFFSET = ZoneOffsetType.INSTANCE;
|
||||
|
||||
/**
|
||||
* The standard Hibernate type for mapping {@link java.util.TimeZone} to JDBC {@link java.sql.Types#VARCHAR VARCHAR}.
|
||||
*
|
||||
@ -927,6 +935,13 @@ public static void prime(TypeConfiguration typeConfiguration) {
|
||||
"timezone", TimeZone.class.getName()
|
||||
);
|
||||
|
||||
handle(
|
||||
ZONE_OFFSET,
|
||||
"org.hibernate.type.ZoneOffsetType",
|
||||
basicTypeRegistry,
|
||||
ZoneOffset.class.getSimpleName(), ZoneOffset.class.getName()
|
||||
);
|
||||
|
||||
handle(
|
||||
URL,
|
||||
"org.hibernate.type.UrlType",
|
||||
|
@ -50,14 +50,6 @@ public String[] getRegistrationKeys() {
|
||||
// return true;
|
||||
// }
|
||||
|
||||
public String objectToSQLString(Date value, Dialect dialect) throws Exception {
|
||||
Time jdbcTime = Time.class.isInstance( value )
|
||||
? ( Time ) value
|
||||
: new Time( value.getTime() );
|
||||
// TODO : use JDBC time literal escape syntax? -> {t 'time-string'} in hh:mm:ss format
|
||||
return StringType.INSTANCE.objectToSQLString( jdbcTime.toString(), dialect );
|
||||
}
|
||||
|
||||
@Override
|
||||
public AllowableTemporalParameterType resolveTemporalPrecision(
|
||||
TemporalType temporalPrecision,
|
||||
|
@ -62,15 +62,6 @@ public Comparator<Date> getComparator() {
|
||||
return getJavaTypeDescriptor().getComparator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String objectToSQLString(Date value, Dialect dialect) throws Exception {
|
||||
final Timestamp ts = Timestamp.class.isInstance( value )
|
||||
? ( Timestamp ) value
|
||||
: new Timestamp( value.getTime() );
|
||||
// TODO : use JDBC date literal escape syntax? -> {d 'date-string'} in yyyy-mm-dd hh:mm:ss[.f...] format
|
||||
return StringType.INSTANCE.objectToSQLString( ts.toString(), dialect );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date fromStringValue(String xml) throws HibernateException {
|
||||
return fromString( xml );
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.dialect.Dialect;
|
||||
import org.hibernate.type.descriptor.java.ZoneOffsetJavaDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor;
|
||||
|
||||
import java.time.ZoneOffset;
|
||||
|
||||
/**
|
||||
* A type mapping {@link java.sql.Types#VARCHAR VARCHAR} and {@link ZoneOffset}
|
||||
*
|
||||
* @author Gavin King
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class ZoneOffsetType
|
||||
extends AbstractSingleColumnStandardBasicType<ZoneOffset>
|
||||
implements LiteralType<ZoneOffset> {
|
||||
|
||||
public static final ZoneOffsetType INSTANCE = new ZoneOffsetType();
|
||||
|
||||
public ZoneOffsetType() {
|
||||
super( VarcharTypeDescriptor.INSTANCE, ZoneOffsetJavaDescriptor.INSTANCE );
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return ZoneOffset.class.getSimpleName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean registerUnderJavaType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String objectToSQLString(ZoneOffset value, Dialect dialect) throws Exception {
|
||||
return StringType.INSTANCE.objectToSQLString( value.getId(), dialect );
|
||||
}
|
||||
|
||||
}
|
@ -20,6 +20,7 @@
|
||||
import org.hibernate.metamodel.model.domain.AllowableTemporalParameterType;
|
||||
import org.hibernate.type.descriptor.java.ZonedDateTimeJavaDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.TimestampTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.TimestampWithTimeZoneDescriptor;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
/**
|
||||
@ -34,15 +35,8 @@ public class ZonedDateTimeType
|
||||
*/
|
||||
public static final ZonedDateTimeType INSTANCE = new ZonedDateTimeType();
|
||||
|
||||
public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern( "yyyy-MM-dd HH:mm:ss.S VV", Locale.ENGLISH );
|
||||
|
||||
public ZonedDateTimeType() {
|
||||
super( TimestampTypeDescriptor.INSTANCE, ZonedDateTimeJavaDescriptor.INSTANCE );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String objectToSQLString(ZonedDateTime value, Dialect dialect) throws Exception {
|
||||
return "{ts '" + FORMATTER.format( value ) + "'}";
|
||||
super( TimestampWithTimeZoneDescriptor.INSTANCE, ZonedDateTimeJavaDescriptor.INSTANCE );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -12,11 +12,11 @@
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import org.hibernate.type.LocalDateType;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
|
||||
/**
|
||||
@ -37,12 +37,12 @@ public LocalDateJavaDescriptor() {
|
||||
|
||||
@Override
|
||||
public String toString(LocalDate value) {
|
||||
return LocalDateType.FORMATTER.format( value );
|
||||
return DateTimeFormatter.ISO_LOCAL_DATE.format( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDate fromString(String string) {
|
||||
return LocalDate.from( LocalDateType.FORMATTER.parse( string ) );
|
||||
return LocalDate.from( DateTimeFormatter.ISO_LOCAL_DATE.parse( string ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -10,12 +10,12 @@
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.type.LocalDateTimeType;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
|
||||
/**
|
||||
@ -36,12 +36,12 @@ public LocalDateTimeJavaDescriptor() {
|
||||
|
||||
@Override
|
||||
public String toString(LocalDateTime value) {
|
||||
return LocalDateTimeType.FORMATTER.format( value );
|
||||
return DateTimeFormatter.ISO_DATE_TIME.format( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalDateTime fromString(String string) {
|
||||
return LocalDateTime.from( LocalDateTimeType.FORMATTER.parse( string ) );
|
||||
return LocalDateTime.from( DateTimeFormatter.ISO_DATE_TIME.parse( string ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -14,12 +14,12 @@
|
||||
import java.time.LocalTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.type.LocalTimeType;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
|
||||
/**
|
||||
@ -40,12 +40,12 @@ public LocalTimeJavaDescriptor() {
|
||||
|
||||
@Override
|
||||
public String toString(LocalTime value) {
|
||||
return LocalTimeType.FORMATTER.format( value );
|
||||
return DateTimeFormatter.ISO_LOCAL_TIME.format( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalTime fromString(String string) {
|
||||
return LocalTime.from( LocalTimeType.FORMATTER.parse( string ) );
|
||||
return LocalTime.from( DateTimeFormatter.ISO_LOCAL_TIME.parse( string ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -10,16 +10,17 @@
|
||||
import java.time.Instant;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.type.OffsetDateTimeType;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
|
||||
/**
|
||||
* Java type descriptor for the LocalDateTime type.
|
||||
* Java type descriptor for the {@link OffsetDateTime} type.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@ -36,12 +37,12 @@ public OffsetDateTimeJavaDescriptor() {
|
||||
|
||||
@Override
|
||||
public String toString(OffsetDateTime value) {
|
||||
return OffsetDateTimeType.FORMATTER.format( value );
|
||||
return DateTimeFormatter.ISO_OFFSET_DATE_TIME.format( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public OffsetDateTime fromString(String string) {
|
||||
return OffsetDateTime.from( OffsetDateTimeType.FORMATTER.parse( string ) );
|
||||
return OffsetDateTime.from( DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse( string ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -55,6 +56,10 @@ public <X> X unwrap(OffsetDateTime offsetDateTime, Class<X> type, WrapperOptions
|
||||
return (X) offsetDateTime;
|
||||
}
|
||||
|
||||
if ( ZonedDateTime.class.isAssignableFrom( type ) ) {
|
||||
return (X) offsetDateTime.toZonedDateTime();
|
||||
}
|
||||
|
||||
if ( Calendar.class.isAssignableFrom( type ) ) {
|
||||
return (X) GregorianCalendar.from( offsetDateTime.toZonedDateTime() );
|
||||
}
|
||||
@ -109,6 +114,11 @@ public <X> OffsetDateTime wrap(X value, WrapperOptions options) {
|
||||
return (OffsetDateTime) value;
|
||||
}
|
||||
|
||||
if ( ZonedDateTime.class.isInstance( value ) ) {
|
||||
ZonedDateTime zonedDateTime = (ZonedDateTime) value;
|
||||
return OffsetDateTime.of( zonedDateTime.toLocalDateTime(), zonedDateTime.getOffset() );
|
||||
}
|
||||
|
||||
if ( Timestamp.class.isInstance( value ) ) {
|
||||
final Timestamp ts = (Timestamp) value;
|
||||
/*
|
||||
|
@ -14,12 +14,12 @@
|
||||
import java.time.OffsetTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.type.OffsetTimeType;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
|
||||
/**
|
||||
@ -40,12 +40,12 @@ public OffsetTimeJavaDescriptor() {
|
||||
|
||||
@Override
|
||||
public String toString(OffsetTime value) {
|
||||
return OffsetTimeType.FORMATTER.format( value );
|
||||
return DateTimeFormatter.ISO_OFFSET_TIME.format( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public OffsetTime fromString(String string) {
|
||||
return OffsetTime.from( OffsetTimeType.FORMATTER.parse( string ) );
|
||||
return OffsetTime.from( DateTimeFormatter.ISO_OFFSET_TIME.parse( string ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.java;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptorIndicators;
|
||||
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link ZoneOffset} handling.
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class ZoneOffsetJavaDescriptor extends AbstractTypeDescriptor<ZoneOffset> {
|
||||
public static final ZoneOffsetJavaDescriptor INSTANCE = new ZoneOffsetJavaDescriptor();
|
||||
|
||||
public static class ZoneOffsetComparator implements Comparator<ZoneOffset> {
|
||||
public static final ZoneOffsetComparator INSTANCE = new ZoneOffsetComparator();
|
||||
|
||||
public int compare(ZoneOffset o1, ZoneOffset o2) {
|
||||
return o1.getId().compareTo( o2.getId() );
|
||||
}
|
||||
}
|
||||
|
||||
public ZoneOffsetJavaDescriptor() {
|
||||
super( ZoneOffset.class );
|
||||
}
|
||||
|
||||
public String toString(ZoneOffset value) {
|
||||
return value.getId();
|
||||
}
|
||||
|
||||
public ZoneOffset fromString(String string) {
|
||||
return ZoneOffset.of( string );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlTypeDescriptor getJdbcRecommendedSqlType(SqlTypeDescriptorIndicators context) {
|
||||
return StringTypeDescriptor.INSTANCE.getJdbcRecommendedSqlType( context );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Comparator<ZoneOffset> getComparator() {
|
||||
return ZoneOffsetComparator.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked" })
|
||||
public <X> X unwrap(ZoneOffset value, Class<X> type, WrapperOptions wrapperOptions) {
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
if ( String.class.isAssignableFrom( type ) ) {
|
||||
return (X) toString( value );
|
||||
}
|
||||
throw unknownUnwrap( type );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ZoneOffset wrap(X value, WrapperOptions wrapperOptions) {
|
||||
if ( value == null ) {
|
||||
return null;
|
||||
}
|
||||
if ( String.class.isInstance( value ) ) {
|
||||
return fromString( (String) value );
|
||||
}
|
||||
throw unknownWrap( value.getClass() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDefaultSqlLength(Dialect dialect) {
|
||||
return 6;
|
||||
}
|
||||
}
|
@ -8,18 +8,19 @@
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Instant;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.type.ZonedDateTimeType;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
|
||||
/**
|
||||
* Java type descriptor for the LocalDateTime type.
|
||||
* Java type descriptor for the {@link ZonedDateTime} type.
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
@ -36,12 +37,12 @@ public ZonedDateTimeJavaDescriptor() {
|
||||
|
||||
@Override
|
||||
public String toString(ZonedDateTime value) {
|
||||
return ZonedDateTimeType.FORMATTER.format( value );
|
||||
return DateTimeFormatter.ISO_ZONED_DATE_TIME.format( value );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ZonedDateTime fromString(String string) {
|
||||
return ZonedDateTime.from( ZonedDateTimeType.FORMATTER.parse( string ) );
|
||||
return ZonedDateTime.from( DateTimeFormatter.ISO_ZONED_DATE_TIME.parse( string ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -55,6 +56,10 @@ public <X> X unwrap(ZonedDateTime zonedDateTime, Class<X> type, WrapperOptions o
|
||||
return (X) zonedDateTime;
|
||||
}
|
||||
|
||||
if ( OffsetDateTime.class.isAssignableFrom( type ) ) {
|
||||
return (X) OffsetDateTime.of( zonedDateTime.toLocalDateTime(), zonedDateTime.getOffset() );
|
||||
}
|
||||
|
||||
if ( Calendar.class.isAssignableFrom( type ) ) {
|
||||
return (X) GregorianCalendar.from( zonedDateTime );
|
||||
}
|
||||
@ -109,6 +114,11 @@ public <X> ZonedDateTime wrap(X value, WrapperOptions options) {
|
||||
return (ZonedDateTime) value;
|
||||
}
|
||||
|
||||
if ( OffsetDateTime.class.isInstance( value ) ) {
|
||||
OffsetDateTime offsetDateTime = (OffsetDateTime) value;
|
||||
return offsetDateTime.toZonedDateTime();
|
||||
}
|
||||
|
||||
if ( java.sql.Timestamp.class.isInstance( value ) ) {
|
||||
final Timestamp ts = (Timestamp) value;
|
||||
/*
|
||||
|
@ -18,6 +18,11 @@
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
@ -112,6 +117,11 @@ private static ConcurrentHashMap<Class, Integer> buildJavaClassToJdbcTypeCodeMap
|
||||
workMap.put( java.sql.Date.class, Types.DATE );
|
||||
workMap.put( Time.class, Types.TIME );
|
||||
workMap.put( Timestamp.class, Types.TIMESTAMP );
|
||||
workMap.put( LocalTime.class, Types.TIME );
|
||||
workMap.put( LocalDate.class, Types.DATE );
|
||||
workMap.put( LocalDateTime.class, Types.TIMESTAMP );
|
||||
workMap.put( OffsetDateTime.class, Types.TIMESTAMP_WITH_TIMEZONE );
|
||||
workMap.put( ZonedDateTime.class, Types.TIMESTAMP_WITH_TIMEZONE );
|
||||
workMap.put( Blob.class, Types.BLOB );
|
||||
workMap.put( Clob.class, Types.CLOB );
|
||||
workMap.put( Array.class, Types.ARRAY );
|
||||
|
@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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.sql;
|
||||
|
||||
import org.hibernate.type.descriptor.ValueBinder;
|
||||
import org.hibernate.type.descriptor.ValueExtractor;
|
||||
import org.hibernate.type.descriptor.WrapperOptions;
|
||||
import org.hibernate.type.descriptor.java.BasicJavaDescriptor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.sql.internal.JdbcLiteralFormatterTemporal;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
||||
import javax.persistence.TemporalType;
|
||||
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.OffsetDateTime;
|
||||
|
||||
/**
|
||||
* Descriptor for {@link Types#TIMESTAMP_WITH_TIMEZONE TIMESTAMP_WITH_TIMEZONE} handling.
|
||||
*
|
||||
* @author Gavin King
|
||||
*/
|
||||
public class TimestampWithTimeZoneDescriptor implements SqlTypeDescriptor {
|
||||
public static final TimestampWithTimeZoneDescriptor INSTANCE = new TimestampWithTimeZoneDescriptor();
|
||||
|
||||
public TimestampWithTimeZoneDescriptor() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSqlType() {
|
||||
return Types.TIMESTAMP_WITH_TIMEZONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeRemapped() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> BasicJavaDescriptor<T> getJdbcRecommendedJavaTypeMapping(TypeConfiguration typeConfiguration) {
|
||||
return (BasicJavaDescriptor<T>) typeConfiguration.getJavaTypeDescriptorRegistry().getDescriptor( OffsetDateTime.class );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> JdbcLiteralFormatter<T> getJdbcLiteralFormatter(JavaTypeDescriptor<T> javaTypeDescriptor) {
|
||||
return new JdbcLiteralFormatterTemporal( javaTypeDescriptor, TemporalType.TIMESTAMP );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicBinder<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected void doBind(
|
||||
PreparedStatement st,
|
||||
X value,
|
||||
int index,
|
||||
WrapperOptions wrapperOptions) throws SQLException {
|
||||
try {
|
||||
final OffsetDateTime dateTime = javaTypeDescriptor.unwrap( value, OffsetDateTime.class, wrapperOptions.getSession() );
|
||||
// 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 = javaTypeDescriptor.unwrap( value, Timestamp.class, wrapperOptions.getSession() );
|
||||
st.setTimestamp( index, timestamp );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBind(
|
||||
CallableStatement st,
|
||||
X value,
|
||||
String name,
|
||||
WrapperOptions wrapperOptions)
|
||||
throws SQLException {
|
||||
try {
|
||||
final OffsetDateTime dateTime = javaTypeDescriptor.unwrap( value, OffsetDateTime.class, wrapperOptions.getSession() );
|
||||
// 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 = javaTypeDescriptor.unwrap( value, Timestamp.class, wrapperOptions.getSession() );
|
||||
st.setTimestamp( name, timestamp );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
|
||||
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
|
||||
@Override
|
||||
protected X doExtract(ResultSet rs, int position, WrapperOptions wrapperOptions) throws SQLException {
|
||||
try {
|
||||
// supposed to be supported in JDBC 4.2
|
||||
return javaTypeDescriptor.wrap( rs.getObject( position, OffsetDateTime.class ), wrapperOptions.getSession() );
|
||||
}
|
||||
catch (SQLException|AbstractMethodError e) {
|
||||
// fall back to treating it as a JDBC Timestamp
|
||||
return javaTypeDescriptor.wrap( rs.getTimestamp( position ), wrapperOptions.getSession() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, int position, WrapperOptions wrapperOptions) throws SQLException {
|
||||
try {
|
||||
// supposed to be supported in JDBC 4.2
|
||||
return javaTypeDescriptor.wrap( statement.getObject( position, OffsetDateTime.class ), wrapperOptions.getSession() );
|
||||
}
|
||||
catch (SQLException|AbstractMethodError e) {
|
||||
// fall back to treating it as a JDBC Timestamp
|
||||
return javaTypeDescriptor.wrap( statement.getTimestamp( position ), wrapperOptions.getSession() );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions wrapperOptions) throws SQLException {
|
||||
try {
|
||||
// supposed to be supported in JDBC 4.2
|
||||
return javaTypeDescriptor.wrap( statement.getObject( name, OffsetDateTime.class ), wrapperOptions.getSession() );
|
||||
}
|
||||
catch (SQLException|AbstractMethodError e) {
|
||||
// fall back to treating it as a JDBC Timestamp
|
||||
return javaTypeDescriptor.wrap( statement.getTimestamp( name ), wrapperOptions.getSession() );
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user