HHH-13266 Test OffsetTime serialization
This commit is contained in:
parent
759237fb9f
commit
09618a2174
|
@ -0,0 +1,203 @@
|
||||||
|
/*
|
||||||
|
* 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.test.type;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Time;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.sql.Types;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.OffsetTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import org.hibernate.type.descriptor.sql.BigIntTypeDescriptor;
|
||||||
|
import org.hibernate.type.descriptor.sql.TimestampTypeDescriptor;
|
||||||
|
|
||||||
|
import org.junit.runners.Parameterized;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for storage of LocalTime properties.
|
||||||
|
*/
|
||||||
|
public class OffsetTimeTest extends AbstractJavaTimeTypeTest<OffsetTime, OffsetTimeTest.EntityWithOffsetTime> {
|
||||||
|
|
||||||
|
private static class ParametersBuilder extends AbstractParametersBuilder<ParametersBuilder> {
|
||||||
|
public ParametersBuilder add(int hour, int minute, int second, int nanosecond, String offset, ZoneId defaultTimeZone) {
|
||||||
|
if ( !isNanosecondPrecisionSupported() ) {
|
||||||
|
nanosecond = 0;
|
||||||
|
}
|
||||||
|
return add( defaultTimeZone, hour, minute, second, nanosecond, offset, 1970, 1, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
public ParametersBuilder addPersistedWithoutHibernate(int yearWhenPersistedWithoutHibernate,
|
||||||
|
int monthWhenPersistedWithoutHibernate, int dayWhenPersistedWithoutHibernate,
|
||||||
|
int hour, int minute, int second, int nanosecond, String offset, ZoneId defaultTimeZone) {
|
||||||
|
if ( !isNanosecondPrecisionSupported() ) {
|
||||||
|
nanosecond = 0;
|
||||||
|
}
|
||||||
|
return add(
|
||||||
|
defaultTimeZone, hour, minute, second, nanosecond, offset,
|
||||||
|
yearWhenPersistedWithoutHibernate,
|
||||||
|
monthWhenPersistedWithoutHibernate, dayWhenPersistedWithoutHibernate
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Parameterized.Parameters(name = "{1}:{2}:{3}.{4}[{5}] (JDBC write date: {6}-{7}-{8}) {0}")
|
||||||
|
public static List<Object[]> data() {
|
||||||
|
return new ParametersBuilder()
|
||||||
|
.alsoTestRemappingsWithH2( TimeAsTimestampRemappingH2Dialect.class )
|
||||||
|
// None of these values was affected by HHH-13266 (JDK-8061577)
|
||||||
|
.add( 19, 19, 1, 0, "+10:00", ZONE_UTC_MINUS_8 )
|
||||||
|
.add( 19, 19, 1, 0, "+01:30", ZONE_UTC_MINUS_8 )
|
||||||
|
.add( 19, 19, 1, 0, "-06:00", ZONE_UTC_MINUS_8 )
|
||||||
|
.add( 19, 19, 1, 0, "+10:00", ZONE_PARIS )
|
||||||
|
.add( 19, 19, 1, 0, "+01:30", ZONE_PARIS )
|
||||||
|
.add( 19, 19, 1, 500, "+01:00", ZONE_PARIS )
|
||||||
|
.add( 19, 19, 1, 0, "-08:00", ZONE_PARIS )
|
||||||
|
.add( 0, 0, 0, 0, "+01:00", ZONE_GMT )
|
||||||
|
.add( 0, 0, 0, 0, "+00:00", ZONE_GMT )
|
||||||
|
.add( 0, 0, 0, 0, "-01:00", ZONE_GMT )
|
||||||
|
.add( 0, 0, 0, 0, "+00:00", ZONE_OSLO )
|
||||||
|
.add( 0, 9, 20, 0, "+00:09:21", ZONE_PARIS )
|
||||||
|
.add( 0, 19, 31, 0, "+00:19:32", ZONE_PARIS )
|
||||||
|
.add( 0, 19, 31, 0, "+00:19:32", ZONE_AMSTERDAM )
|
||||||
|
.add( 0, 0, 0, 0, "+00:19:32", ZONE_AMSTERDAM )
|
||||||
|
.addPersistedWithoutHibernate( 1892, 1, 1, 0, 0, 0, 0, "+00:00", ZONE_OSLO )
|
||||||
|
.addPersistedWithoutHibernate( 1900, 1, 1, 0, 9, 20, 0, "+00:09:21", ZONE_PARIS )
|
||||||
|
.addPersistedWithoutHibernate( 1900, 1, 1, 0, 19, 31, 0, "+00:19:32", ZONE_PARIS )
|
||||||
|
.addPersistedWithoutHibernate( 1900, 1, 1, 0, 19, 31, 0, "+00:19:32", ZONE_AMSTERDAM )
|
||||||
|
.addPersistedWithoutHibernate( 1600, 1, 1, 0, 0, 0, 0, "+00:19:32", ZONE_AMSTERDAM )
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final int hour;
|
||||||
|
private final int minute;
|
||||||
|
private final int second;
|
||||||
|
private final int nanosecond;
|
||||||
|
private final String offset;
|
||||||
|
|
||||||
|
private final int yearWhenPersistedWithoutHibernate;
|
||||||
|
private final int monthWhenPersistedWithoutHibernate;
|
||||||
|
private final int dayWhenPersistedWithoutHibernate;
|
||||||
|
|
||||||
|
public OffsetTimeTest(EnvironmentParameters env, int hour, int minute, int second, int nanosecond, String offset,
|
||||||
|
int yearWhenPersistedWithoutHibernate, int monthWhenPersistedWithoutHibernate, int dayWhenPersistedWithoutHibernate) {
|
||||||
|
super( env );
|
||||||
|
this.hour = hour;
|
||||||
|
this.minute = minute;
|
||||||
|
this.second = second;
|
||||||
|
this.nanosecond = nanosecond;
|
||||||
|
this.offset = offset;
|
||||||
|
this.yearWhenPersistedWithoutHibernate = yearWhenPersistedWithoutHibernate;
|
||||||
|
this.monthWhenPersistedWithoutHibernate = monthWhenPersistedWithoutHibernate;
|
||||||
|
this.dayWhenPersistedWithoutHibernate = dayWhenPersistedWithoutHibernate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<EntityWithOffsetTime> getEntityType() {
|
||||||
|
return EntityWithOffsetTime.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected EntityWithOffsetTime createEntityForHibernateWrite(int id) {
|
||||||
|
return new EntityWithOffsetTime( id, getOriginalPropertyValue() );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected OffsetTime getOriginalPropertyValue() {
|
||||||
|
return OffsetTime.of( hour, minute, second, nanosecond, ZoneOffset.of( offset ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected OffsetTime getExpectedPropertyValueAfterHibernateRead() {
|
||||||
|
// For some reason, the offset is not stored, so the restored values use the offset from the default JVM timezone.
|
||||||
|
if ( TimeAsTimestampRemappingH2Dialect.class.equals( getRemappingDialectClass() ) ) {
|
||||||
|
return getOriginalPropertyValue().withOffsetSameLocal( OffsetDateTime.now().getOffset() );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// When storing time as java.sql.Time, we only get second precision (not nanosecond)
|
||||||
|
return getOriginalPropertyValue().withNano( 0 ).withOffsetSameLocal( OffsetDateTime.now().getOffset() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected OffsetTime getActualPropertyValue(EntityWithOffsetTime entity) {
|
||||||
|
return entity.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setJdbcValueForNonHibernateWrite(PreparedStatement statement, int parameterIndex)
|
||||||
|
throws SQLException {
|
||||||
|
if ( TimeAsTimestampRemappingH2Dialect.class.equals( getRemappingDialectClass() ) ) {
|
||||||
|
statement.setTimestamp(
|
||||||
|
parameterIndex,
|
||||||
|
new Timestamp(
|
||||||
|
yearWhenPersistedWithoutHibernate - 1900,
|
||||||
|
monthWhenPersistedWithoutHibernate - 1,
|
||||||
|
dayWhenPersistedWithoutHibernate,
|
||||||
|
hour, minute, second, nanosecond
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
statement.setTime( parameterIndex, new Time( hour, minute, second ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object getExpectedJdbcValueAfterHibernateWrite() {
|
||||||
|
if ( TimeAsTimestampRemappingH2Dialect.class.equals( getRemappingDialectClass() ) ) {
|
||||||
|
return new Timestamp( 1970 - 1900, 0, 1, hour, minute, second, nanosecond );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return new Time( hour, minute, second );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object getActualJdbcValue(ResultSet resultSet, int columnIndex) throws SQLException {
|
||||||
|
return resultSet.getTimestamp( columnIndex );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = ENTITY_NAME)
|
||||||
|
static final class EntityWithOffsetTime {
|
||||||
|
@Id
|
||||||
|
@Column(name = ID_COLUMN_NAME)
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
@Basic
|
||||||
|
@Column(name = PROPERTY_COLUMN_NAME)
|
||||||
|
private OffsetTime value;
|
||||||
|
|
||||||
|
protected EntityWithOffsetTime() {
|
||||||
|
}
|
||||||
|
|
||||||
|
private EntityWithOffsetTime(int id, OffsetTime value) {
|
||||||
|
this.id = id;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TimeAsTimestampRemappingH2Dialect extends AbstractRemappingH2Dialect {
|
||||||
|
public TimeAsTimestampRemappingH2Dialect() {
|
||||||
|
super( Types.TIME, TimestampTypeDescriptor.INSTANCE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TimeAsBigIntRemappingH2Dialect extends AbstractRemappingH2Dialect {
|
||||||
|
public TimeAsBigIntRemappingH2Dialect() {
|
||||||
|
super( Types.TIME, BigIntTypeDescriptor.INSTANCE );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue