HHH-10399 - Add support for specifying TimeZone for ZonedDateTime type
This commit is contained in:
parent
d229534647
commit
553942d2f9
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate;
|
package org.hibernate;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
|
import org.hibernate.resource.jdbc.spi.PhysicalConnectionHandlingMode;
|
||||||
import org.hibernate.resource.jdbc.spi.StatementInspector;
|
import org.hibernate.resource.jdbc.spi.StatementInspector;
|
||||||
|
@ -174,4 +175,5 @@ public interface SessionBuilder<T extends SessionBuilder> {
|
||||||
*/
|
*/
|
||||||
T clearEventListeners();
|
T clearEventListeners();
|
||||||
|
|
||||||
|
T jdbcTimeZone(TimeZone timeZone);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,14 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.boot.internal;
|
package org.hibernate.boot.internal;
|
||||||
|
|
||||||
|
import java.time.ZoneId;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.hibernate.ConnectionAcquisitionMode;
|
import org.hibernate.ConnectionAcquisitionMode;
|
||||||
import org.hibernate.ConnectionReleaseMode;
|
import org.hibernate.ConnectionReleaseMode;
|
||||||
|
@ -77,6 +79,7 @@ import static org.hibernate.cfg.AvailableSettings.FLUSH_BEFORE_COMPLETION;
|
||||||
import static org.hibernate.cfg.AvailableSettings.GENERATE_STATISTICS;
|
import static org.hibernate.cfg.AvailableSettings.GENERATE_STATISTICS;
|
||||||
import static org.hibernate.cfg.AvailableSettings.HQL_BULK_ID_STRATEGY;
|
import static org.hibernate.cfg.AvailableSettings.HQL_BULK_ID_STRATEGY;
|
||||||
import static org.hibernate.cfg.AvailableSettings.INTERCEPTOR;
|
import static org.hibernate.cfg.AvailableSettings.INTERCEPTOR;
|
||||||
|
import static org.hibernate.cfg.AvailableSettings.JDBC_TIME_ZONE;
|
||||||
import static org.hibernate.cfg.AvailableSettings.JPAQL_STRICT_COMPLIANCE;
|
import static org.hibernate.cfg.AvailableSettings.JPAQL_STRICT_COMPLIANCE;
|
||||||
import static org.hibernate.cfg.AvailableSettings.JTA_TRACK_BY_THREAD;
|
import static org.hibernate.cfg.AvailableSettings.JTA_TRACK_BY_THREAD;
|
||||||
import static org.hibernate.cfg.AvailableSettings.LOG_SESSION_METRICS;
|
import static org.hibernate.cfg.AvailableSettings.LOG_SESSION_METRICS;
|
||||||
|
@ -591,6 +594,7 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
||||||
private boolean commentsEnabled;
|
private boolean commentsEnabled;
|
||||||
private PhysicalConnectionHandlingMode connectionHandlingMode;
|
private PhysicalConnectionHandlingMode connectionHandlingMode;
|
||||||
private boolean wrapResultSetsEnabled;
|
private boolean wrapResultSetsEnabled;
|
||||||
|
private TimeZone jdbcTimeZone;
|
||||||
|
|
||||||
private Map<String, SQLFunction> sqlFunctions;
|
private Map<String, SQLFunction> sqlFunctions;
|
||||||
|
|
||||||
|
@ -767,6 +771,22 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
||||||
configurationSettings,
|
configurationSettings,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
Object jdbcTimeZoneValue = configurationSettings.get(
|
||||||
|
JDBC_TIME_ZONE
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( jdbcTimeZoneValue instanceof TimeZone ) {
|
||||||
|
this.jdbcTimeZone = (TimeZone) jdbcTimeZoneValue;
|
||||||
|
}
|
||||||
|
else if ( jdbcTimeZoneValue instanceof ZoneId ) {
|
||||||
|
this.jdbcTimeZone = TimeZone.getTimeZone( (ZoneId) jdbcTimeZoneValue );
|
||||||
|
}
|
||||||
|
else if ( jdbcTimeZoneValue instanceof String ) {
|
||||||
|
this.jdbcTimeZone = TimeZone.getTimeZone( ZoneId.of((String) jdbcTimeZoneValue) );
|
||||||
|
}
|
||||||
|
else if ( jdbcTimeZoneValue != null ) {
|
||||||
|
throw new IllegalArgumentException( "Configuration property " + JDBC_TIME_ZONE + " value [" + jdbcTimeZoneValue + "] is not supported!" );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Interceptor determineInterceptor(Map configurationSettings, StrategySelector strategySelector) {
|
private static Interceptor determineInterceptor(Map configurationSettings, StrategySelector strategySelector) {
|
||||||
|
@ -1180,6 +1200,11 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
||||||
public boolean isPreferUserTransaction() {
|
public boolean isPreferUserTransaction() {
|
||||||
return this.preferUserTransaction;
|
return this.preferUserTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeZone getJdbcTimeZone() {
|
||||||
|
return this.jdbcTimeZone;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1480,4 +1505,9 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
|
||||||
public boolean isPreferUserTransaction() {
|
public boolean isPreferUserTransaction() {
|
||||||
return options.isPreferUserTransaction();
|
return options.isPreferUserTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeZone getJdbcTimeZone() {
|
||||||
|
return options.getJdbcTimeZone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.boot.internal;
|
package org.hibernate.boot.internal;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.hibernate.ConnectionReleaseMode;
|
import org.hibernate.ConnectionReleaseMode;
|
||||||
import org.hibernate.CustomEntityDirtinessStrategy;
|
import org.hibernate.CustomEntityDirtinessStrategy;
|
||||||
|
@ -118,6 +119,7 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
|
||||||
private final boolean commentsEnabled;
|
private final boolean commentsEnabled;
|
||||||
private final PhysicalConnectionHandlingMode physicalConnectionHandlingMode;
|
private final PhysicalConnectionHandlingMode physicalConnectionHandlingMode;
|
||||||
private final boolean wrapResultSetsEnabled;
|
private final boolean wrapResultSetsEnabled;
|
||||||
|
private final TimeZone jdbcTimeZone;
|
||||||
|
|
||||||
private final Map<String, SQLFunction> sqlFunctions;
|
private final Map<String, SQLFunction> sqlFunctions;
|
||||||
|
|
||||||
|
@ -191,6 +193,8 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
|
||||||
this.commentsEnabled = state.isCommentsEnabled();
|
this.commentsEnabled = state.isCommentsEnabled();
|
||||||
|
|
||||||
this.sqlFunctions = state.getCustomSqlFunctionMap();
|
this.sqlFunctions = state.getCustomSqlFunctionMap();
|
||||||
|
|
||||||
|
this.jdbcTimeZone = state.getJdbcTimeZone();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -496,4 +500,9 @@ public class SessionFactoryOptionsImpl implements SessionFactoryOptions {
|
||||||
public boolean isPreferUserTransaction() {
|
public boolean isPreferUserTransaction() {
|
||||||
return preferUserTransaction;
|
return preferUserTransaction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeZone getJdbcTimeZone() {
|
||||||
|
return jdbcTimeZone;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.boot.internal;
|
package org.hibernate.boot.internal;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.hibernate.ConnectionReleaseMode;
|
import org.hibernate.ConnectionReleaseMode;
|
||||||
import org.hibernate.CustomEntityDirtinessStrategy;
|
import org.hibernate.CustomEntityDirtinessStrategy;
|
||||||
|
@ -165,4 +166,6 @@ public interface SessionFactoryOptionsState {
|
||||||
Map<String, SQLFunction> getCustomSqlFunctionMap();
|
Map<String, SQLFunction> getCustomSqlFunctionMap();
|
||||||
|
|
||||||
boolean isPreferUserTransaction();
|
boolean isPreferUserTransaction();
|
||||||
|
|
||||||
|
TimeZone getJdbcTimeZone();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.boot.spi;
|
package org.hibernate.boot.spi;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.hibernate.ConnectionReleaseMode;
|
import org.hibernate.ConnectionReleaseMode;
|
||||||
import org.hibernate.CustomEntityDirtinessStrategy;
|
import org.hibernate.CustomEntityDirtinessStrategy;
|
||||||
|
@ -348,4 +349,9 @@ public class AbstractDelegatingSessionFactoryOptions implements SessionFactoryOp
|
||||||
public Class<? extends Interceptor> getStatelessInterceptorImplementor() {
|
public Class<? extends Interceptor> getStatelessInterceptorImplementor() {
|
||||||
return delegate.getStatelessInterceptorImplementor();
|
return delegate.getStatelessInterceptorImplementor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeZone getJdbcTimeZone() {
|
||||||
|
return delegate.getJdbcTimeZone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.boot.spi;
|
package org.hibernate.boot.spi;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.hibernate.ConnectionReleaseMode;
|
import org.hibernate.ConnectionReleaseMode;
|
||||||
import org.hibernate.CustomEntityDirtinessStrategy;
|
import org.hibernate.CustomEntityDirtinessStrategy;
|
||||||
|
@ -19,7 +20,6 @@ import org.hibernate.SessionFactoryObserver;
|
||||||
import org.hibernate.boot.SchemaAutoTooling;
|
import org.hibernate.boot.SchemaAutoTooling;
|
||||||
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
import org.hibernate.boot.TempTableDdlTransactionHandling;
|
||||||
import org.hibernate.boot.registry.StandardServiceRegistry;
|
import org.hibernate.boot.registry.StandardServiceRegistry;
|
||||||
import org.hibernate.cache.spi.CacheKeysFactory;
|
|
||||||
import org.hibernate.cache.spi.QueryCacheFactory;
|
import org.hibernate.cache.spi.QueryCacheFactory;
|
||||||
import org.hibernate.cfg.BaselineSessionEventsListenerBuilder;
|
import org.hibernate.cfg.BaselineSessionEventsListenerBuilder;
|
||||||
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
|
||||||
|
@ -205,4 +205,6 @@ public interface SessionFactoryOptions {
|
||||||
boolean isAllowOutOfTransactionUpdateOperations();
|
boolean isAllowOutOfTransactionUpdateOperations();
|
||||||
|
|
||||||
boolean isReleaseResourcesOnCloseEnabled();
|
boolean isReleaseResourcesOnCloseEnabled();
|
||||||
|
|
||||||
|
TimeZone getJdbcTimeZone();
|
||||||
}
|
}
|
||||||
|
|
|
@ -710,6 +710,11 @@ public interface AvailableSettings {
|
||||||
*/
|
*/
|
||||||
String BATCH_VERSIONED_DATA = "hibernate.jdbc.batch_versioned_data";
|
String BATCH_VERSIONED_DATA = "hibernate.jdbc.batch_versioned_data";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default JDBC TimeZone.
|
||||||
|
*/
|
||||||
|
String JDBC_TIME_ZONE = "hibernate.jdbc.time_zone";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enable automatic session close at end of transaction
|
* Enable automatic session close at end of transaction
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.engine.spi;
|
package org.hibernate.engine.spi;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.hibernate.ConnectionReleaseMode;
|
import org.hibernate.ConnectionReleaseMode;
|
||||||
import org.hibernate.Interceptor;
|
import org.hibernate.Interceptor;
|
||||||
|
@ -99,4 +100,10 @@ public abstract class AbstractDelegatingSessionBuilder implements SessionBuilder
|
||||||
delegate.clearEventListeners();
|
delegate.clearEventListeners();
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SessionBuilder jdbcTimeZone(TimeZone timeZone) {
|
||||||
|
delegate.jdbcTimeZone(timeZone);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TimeZone;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import javax.persistence.EntityGraph;
|
import javax.persistence.EntityGraph;
|
||||||
import javax.persistence.EntityManagerFactory;
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
@ -1166,4 +1167,9 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
|
||||||
public void setJdbcBatchSize(Integer jdbcBatchSize) {
|
public void setJdbcBatchSize(Integer jdbcBatchSize) {
|
||||||
delegate.setJdbcBatchSize( jdbcBatchSize );
|
delegate.setJdbcBatchSize( jdbcBatchSize );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeZone getJdbcTimeZone() {
|
||||||
|
return delegate.getJdbcTimeZone();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import java.io.ObjectOutputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.TimeZone;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import javax.persistence.FlushModeType;
|
import javax.persistence.FlushModeType;
|
||||||
import javax.persistence.Tuple;
|
import javax.persistence.Tuple;
|
||||||
|
@ -109,6 +110,8 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
||||||
private final boolean isTransactionCoordinatorShared;
|
private final boolean isTransactionCoordinatorShared;
|
||||||
private final Interceptor interceptor;
|
private final Interceptor interceptor;
|
||||||
|
|
||||||
|
private final TimeZone jdbcTimeZone;
|
||||||
|
|
||||||
private FlushMode flushMode;
|
private FlushMode flushMode;
|
||||||
private boolean autoJoinTransactions;
|
private boolean autoJoinTransactions;
|
||||||
|
|
||||||
|
@ -152,6 +155,7 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
||||||
}
|
}
|
||||||
|
|
||||||
this.interceptor = interpret( options.getInterceptor() );
|
this.interceptor = interpret( options.getInterceptor() );
|
||||||
|
this.jdbcTimeZone = options.getJdbcTimeZone();
|
||||||
|
|
||||||
final StatementInspector statementInspector = interpret( options.getStatementInspector() );
|
final StatementInspector statementInspector = interpret( options.getStatementInspector() );
|
||||||
this.jdbcSessionContext = new JdbcSessionContextImpl( this, statementInspector );
|
this.jdbcSessionContext = new JdbcSessionContextImpl( this, statementInspector );
|
||||||
|
@ -487,6 +491,11 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
|
||||||
return remapped == null ? sqlTypeDescriptor : remapped;
|
return remapped == null ? sqlTypeDescriptor : remapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeZone getJdbcTimeZone() {
|
||||||
|
return jdbcTimeZone;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JdbcServices getJdbcServices() {
|
public JdbcServices getJdbcServices() {
|
||||||
return getFactory().getJdbcServices();
|
return getFactory().getJdbcServices();
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.internal;
|
package org.hibernate.internal;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.hibernate.FlushMode;
|
import org.hibernate.FlushMode;
|
||||||
import org.hibernate.Interceptor;
|
import org.hibernate.Interceptor;
|
||||||
|
@ -42,6 +43,7 @@ public interface SessionCreationOptions {
|
||||||
|
|
||||||
String getTenantIdentifier();
|
String getTenantIdentifier();
|
||||||
|
|
||||||
|
TimeZone getJdbcTimeZone();
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// deprecations
|
// deprecations
|
||||||
|
@ -62,5 +64,4 @@ public interface SessionCreationOptions {
|
||||||
AfterCompletionAction getAfterCompletionAction();
|
AfterCompletionAction getAfterCompletionAction();
|
||||||
|
|
||||||
ManagedFlushChecker getManagedFlushChecker();
|
ManagedFlushChecker getManagedFlushChecker();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.TimeZone;
|
||||||
import javax.naming.Reference;
|
import javax.naming.Reference;
|
||||||
import javax.naming.StringRefAddr;
|
import javax.naming.StringRefAddr;
|
||||||
import javax.persistence.EntityGraph;
|
import javax.persistence.EntityGraph;
|
||||||
|
@ -1073,6 +1074,8 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
|
||||||
private boolean autoClose;
|
private boolean autoClose;
|
||||||
private boolean autoClear;
|
private boolean autoClear;
|
||||||
private String tenantIdentifier;
|
private String tenantIdentifier;
|
||||||
|
private TimeZone jdbcTimeZone;
|
||||||
|
|
||||||
private List<SessionEventListener> listeners;
|
private List<SessionEventListener> listeners;
|
||||||
|
|
||||||
//todo : expose setting
|
//todo : expose setting
|
||||||
|
@ -1094,6 +1097,7 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
|
||||||
if ( sessionFactory.getCurrentTenantIdentifierResolver() != null ) {
|
if ( sessionFactory.getCurrentTenantIdentifierResolver() != null ) {
|
||||||
tenantIdentifier = sessionFactory.getCurrentTenantIdentifierResolver().resolveCurrentTenantIdentifier();
|
tenantIdentifier = sessionFactory.getCurrentTenantIdentifierResolver().resolveCurrentTenantIdentifier();
|
||||||
}
|
}
|
||||||
|
this.jdbcTimeZone = sessionFactory.getSessionFactoryOptions().getJdbcTimeZone();
|
||||||
|
|
||||||
listeners = sessionFactory.getSessionFactoryOptions().getBaselineSessionEventsListenerBuilder().buildBaselineList();
|
listeners = sessionFactory.getSessionFactoryOptions().getBaselineSessionEventsListenerBuilder().buildBaselineList();
|
||||||
}
|
}
|
||||||
|
@ -1184,6 +1188,10 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
|
||||||
return tenantIdentifier;
|
return tenantIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeZone getJdbcTimeZone() {
|
||||||
|
return jdbcTimeZone;
|
||||||
|
}
|
||||||
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
// SessionBuilder
|
// SessionBuilder
|
||||||
|
@ -1304,6 +1312,12 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
|
||||||
listeners.clear();
|
listeners.clear();
|
||||||
return (T) this;
|
return (T) this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T jdbcTimeZone(TimeZone timeZone) {
|
||||||
|
jdbcTimeZone = timeZone;
|
||||||
|
return (T) this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class StatelessSessionBuilderImpl implements StatelessSessionBuilder, SessionCreationOptions {
|
public static class StatelessSessionBuilderImpl implements StatelessSessionBuilder, SessionCreationOptions {
|
||||||
|
@ -1382,6 +1396,11 @@ public final class SessionFactoryImpl implements SessionFactoryImplementor {
|
||||||
return tenantIdentifier;
|
return tenantIdentifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeZone getJdbcTimeZone() {
|
||||||
|
return sessionFactory.getSessionFactoryOptions().getJdbcTimeZone();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SessionOwner getSessionOwner() {
|
public SessionOwner getSessionOwner() {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -6,6 +6,10 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.type.descriptor;
|
package org.hibernate.type.descriptor;
|
||||||
|
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import org.hibernate.engine.jdbc.LobCreator;
|
import org.hibernate.engine.jdbc.LobCreator;
|
||||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||||
|
|
||||||
|
@ -39,4 +43,14 @@ public interface WrapperOptions {
|
||||||
* @return The remapped descriptor. May be the same as the known descriptor indicating no remapping.
|
* @return The remapped descriptor. May be the same as the known descriptor indicating no remapping.
|
||||||
*/
|
*/
|
||||||
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor);
|
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The JDBC {@link TimeZone} used when persisting Timestamp and DateTime properties into the database.
|
||||||
|
* This setting is used when storing timestamps using the {@link java.sql.PreparedStatement#setTimestamp(int, Timestamp, Calendar)} method.
|
||||||
|
*
|
||||||
|
* This way, the storage {@link TimeZone} can differ from the default JVM TimeZone given by {@link TimeZone#getDefault()}.
|
||||||
|
*
|
||||||
|
* @return JDBC {@link TimeZone}
|
||||||
|
*/
|
||||||
|
public TimeZone getJdbcTimeZone();
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,9 @@ public class TimeTypeDescriptor implements SqlTypeDescriptor {
|
||||||
if ( value instanceof Calendar ) {
|
if ( value instanceof Calendar ) {
|
||||||
st.setTime( index, time, (Calendar) value );
|
st.setTime( index, time, (Calendar) value );
|
||||||
}
|
}
|
||||||
|
else if (options.getJdbcTimeZone() != null) {
|
||||||
|
st.setTime( index, time, Calendar.getInstance( options.getJdbcTimeZone() ) );
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
st.setTime( index, time );
|
st.setTime( index, time );
|
||||||
}
|
}
|
||||||
|
@ -61,6 +64,9 @@ public class TimeTypeDescriptor implements SqlTypeDescriptor {
|
||||||
if ( value instanceof Calendar ) {
|
if ( value instanceof Calendar ) {
|
||||||
st.setTime( name, time, (Calendar) value );
|
st.setTime( name, time, (Calendar) value );
|
||||||
}
|
}
|
||||||
|
else if (options.getJdbcTimeZone() != null) {
|
||||||
|
st.setTime( name, time, Calendar.getInstance( options.getJdbcTimeZone() ) );
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
st.setTime( name, time );
|
st.setTime( name, time );
|
||||||
}
|
}
|
||||||
|
@ -73,17 +79,23 @@ public class TimeTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
|
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
|
||||||
@Override
|
@Override
|
||||||
protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
|
protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
|
||||||
return javaTypeDescriptor.wrap( rs.getTime( name ), options );
|
return options.getJdbcTimeZone() != null ?
|
||||||
|
javaTypeDescriptor.wrap( rs.getTime( name, Calendar.getInstance( options.getJdbcTimeZone() ) ), options ) :
|
||||||
|
javaTypeDescriptor.wrap( rs.getTime( name ), options );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||||
return javaTypeDescriptor.wrap( statement.getTime( index ), options );
|
return options.getJdbcTimeZone() != null ?
|
||||||
|
javaTypeDescriptor.wrap( statement.getTime( index, Calendar.getInstance( options.getJdbcTimeZone() ) ), options ) :
|
||||||
|
javaTypeDescriptor.wrap( statement.getTime( index ), options );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||||
return javaTypeDescriptor.wrap( statement.getTime( name ), options );
|
return options.getJdbcTimeZone() != null ?
|
||||||
|
javaTypeDescriptor.wrap( statement.getTime( name, Calendar.getInstance( options.getJdbcTimeZone() ) ), options ) :
|
||||||
|
javaTypeDescriptor.wrap( statement.getTime( name ), options );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,9 @@ public class TimestampTypeDescriptor implements SqlTypeDescriptor {
|
||||||
if ( value instanceof Calendar ) {
|
if ( value instanceof Calendar ) {
|
||||||
st.setTimestamp( index, timestamp, (Calendar) value );
|
st.setTimestamp( index, timestamp, (Calendar) value );
|
||||||
}
|
}
|
||||||
|
else if (options.getJdbcTimeZone() != null) {
|
||||||
|
st.setTimestamp( index, timestamp, Calendar.getInstance( options.getJdbcTimeZone() ) );
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
st.setTimestamp( index, timestamp );
|
st.setTimestamp( index, timestamp );
|
||||||
}
|
}
|
||||||
|
@ -61,6 +64,9 @@ public class TimestampTypeDescriptor implements SqlTypeDescriptor {
|
||||||
if ( value instanceof Calendar ) {
|
if ( value instanceof Calendar ) {
|
||||||
st.setTimestamp( name, timestamp, (Calendar) value );
|
st.setTimestamp( name, timestamp, (Calendar) value );
|
||||||
}
|
}
|
||||||
|
else if (options.getJdbcTimeZone() != null) {
|
||||||
|
st.setTimestamp( name, timestamp, Calendar.getInstance( options.getJdbcTimeZone() ) );
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
st.setTimestamp( name, timestamp );
|
st.setTimestamp( name, timestamp );
|
||||||
}
|
}
|
||||||
|
@ -73,17 +79,23 @@ public class TimestampTypeDescriptor implements SqlTypeDescriptor {
|
||||||
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
|
return new BasicExtractor<X>( javaTypeDescriptor, this ) {
|
||||||
@Override
|
@Override
|
||||||
protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
|
protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
|
||||||
return javaTypeDescriptor.wrap( rs.getTimestamp( name ), options );
|
return options.getJdbcTimeZone() != null ?
|
||||||
|
javaTypeDescriptor.wrap( rs.getTimestamp( name, Calendar.getInstance( options.getJdbcTimeZone() ) ), options ) :
|
||||||
|
javaTypeDescriptor.wrap( rs.getTimestamp( name ), options );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||||
return javaTypeDescriptor.wrap( statement.getTimestamp( index ), options );
|
return options.getJdbcTimeZone() != null ?
|
||||||
|
javaTypeDescriptor.wrap( statement.getTimestamp( index, Calendar.getInstance( options.getJdbcTimeZone() ) ), options ) :
|
||||||
|
javaTypeDescriptor.wrap( statement.getTimestamp( index ), options );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||||
return javaTypeDescriptor.wrap( statement.getTimestamp( name ), options );
|
return options.getJdbcTimeZone() != null ?
|
||||||
|
javaTypeDescriptor.wrap( statement.getTimestamp( name, Calendar.getInstance( options.getJdbcTimeZone() ) ), options ) :
|
||||||
|
javaTypeDescriptor.wrap( statement.getTimestamp( name ), options );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.test.timestamp;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.sql.Time;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.OffsetTime;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.hibernate.test.util.jdbc.PreparedStatementSpyConnectionProvider;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.anyInt;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class JdbcTimeCustomTimeZoneTest
|
||||||
|
extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider();
|
||||||
|
|
||||||
|
private static final TimeZone TIME_ZONE = TimeZone.getTimeZone(
|
||||||
|
"America/Los_Angeles" );
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Person.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addSettings(Map settings) {
|
||||||
|
settings.put(
|
||||||
|
AvailableSettings.CONNECTION_PROVIDER,
|
||||||
|
connectionProvider
|
||||||
|
);
|
||||||
|
settings.put(
|
||||||
|
AvailableSettings.JDBC_TIME_ZONE,
|
||||||
|
TIME_ZONE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void releaseResources() {
|
||||||
|
super.releaseResources();
|
||||||
|
connectionProvider.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTimeZone() {
|
||||||
|
|
||||||
|
connectionProvider.clear();
|
||||||
|
doInHibernate( this::sessionFactory, s -> {
|
||||||
|
Person person = new Person();
|
||||||
|
person.id = 1L;
|
||||||
|
s.persist( person );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
assertEquals( 1, connectionProvider.getPreparedStatements().size() );
|
||||||
|
PreparedStatement ps = connectionProvider.getPreparedStatements()
|
||||||
|
.get( 0 );
|
||||||
|
try {
|
||||||
|
ArgumentCaptor<Calendar> calendarArgumentCaptor = ArgumentCaptor.forClass(
|
||||||
|
Calendar.class );
|
||||||
|
verify( ps, times( 1 ) ).setTime(
|
||||||
|
anyInt(),
|
||||||
|
any( Time.class ),
|
||||||
|
calendarArgumentCaptor.capture()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
TIME_ZONE,
|
||||||
|
calendarArgumentCaptor.getValue().getTimeZone()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
fail( e.getMessage() );
|
||||||
|
}
|
||||||
|
|
||||||
|
connectionProvider.clear();
|
||||||
|
doInHibernate( this::sessionFactory, s -> {
|
||||||
|
s.doWork( connection -> {
|
||||||
|
try (Statement st = connection.createStatement()) {
|
||||||
|
try (ResultSet rs = st.executeQuery(
|
||||||
|
"select createdOn from Person" )) {
|
||||||
|
while ( rs.next() ) {
|
||||||
|
Time time = rs.getTime( 1 );
|
||||||
|
Time offsetTime = Time.valueOf( OffsetTime.ofInstant(
|
||||||
|
Instant.ofEpochMilli( 0 ),
|
||||||
|
TIME_ZONE.toZoneId()
|
||||||
|
).toLocalTime() );
|
||||||
|
assertEquals( offsetTime, time );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
Person person = s.find( Person.class, 1L );
|
||||||
|
assertEquals(
|
||||||
|
0,
|
||||||
|
person.createdOn.getTime() % TimeUnit.DAYS.toSeconds( 1 )
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Person")
|
||||||
|
public static class Person {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private Time createdOn = new Time( 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
/*
|
||||||
|
* 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.timestamp;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Time;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.hibernate.test.util.jdbc.PreparedStatementSpyConnectionProvider;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.anyInt;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class JdbcTimeDefaultTimeZoneTest
|
||||||
|
extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Person.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addSettings(Map settings) {
|
||||||
|
settings.put(
|
||||||
|
AvailableSettings.CONNECTION_PROVIDER,
|
||||||
|
connectionProvider
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void releaseResources() {
|
||||||
|
super.releaseResources();
|
||||||
|
connectionProvider.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTimeZone() {
|
||||||
|
|
||||||
|
connectionProvider.clear();
|
||||||
|
doInHibernate( this::sessionFactory, s -> {
|
||||||
|
Person person = new Person();
|
||||||
|
person.id = 1L;
|
||||||
|
s.persist( person );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
assertEquals( 1, connectionProvider.getPreparedStatements().size() );
|
||||||
|
PreparedStatement ps = connectionProvider.getPreparedStatements()
|
||||||
|
.get( 0 );
|
||||||
|
try {
|
||||||
|
verify( ps, times( 1 ) ).setTime( anyInt(), any( Time.class ) );
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
fail( e.getMessage() );
|
||||||
|
}
|
||||||
|
|
||||||
|
doInHibernate( this::sessionFactory, s -> {
|
||||||
|
Person person = s.find( Person.class, 1L );
|
||||||
|
assertEquals( 0, person.createdOn.getTime() );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Person")
|
||||||
|
public static class Person {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private Time createdOn = new Time( 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
* 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.timestamp;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.hibernate.test.util.jdbc.PreparedStatementSpyConnectionProvider;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernateSessionBuilder;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.anyInt;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class JdbcTimestampCustomSessionLevelTimeZoneTest
|
||||||
|
extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider();
|
||||||
|
|
||||||
|
private static final TimeZone TIME_ZONE = TimeZone.getTimeZone(
|
||||||
|
"America/Los_Angeles" );
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Person.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addSettings(Map settings) {
|
||||||
|
settings.put(
|
||||||
|
AvailableSettings.CONNECTION_PROVIDER,
|
||||||
|
connectionProvider
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void releaseResources() {
|
||||||
|
super.releaseResources();
|
||||||
|
connectionProvider.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTimeZone() {
|
||||||
|
|
||||||
|
connectionProvider.clear();
|
||||||
|
doInHibernateSessionBuilder( () -> {return sessionFactory().withOptions().jdbcTimeZone( TIME_ZONE);}, s -> {
|
||||||
|
Person person = new Person();
|
||||||
|
person.id = 1L;
|
||||||
|
s.persist( person );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
assertEquals( 1, connectionProvider.getPreparedStatements().size() );
|
||||||
|
PreparedStatement ps = connectionProvider.getPreparedStatements()
|
||||||
|
.get( 0 );
|
||||||
|
try {
|
||||||
|
ArgumentCaptor<Calendar> calendarArgumentCaptor = ArgumentCaptor.forClass(
|
||||||
|
Calendar.class );
|
||||||
|
verify( ps, times( 1 ) ).setTimestamp(
|
||||||
|
anyInt(),
|
||||||
|
any( Timestamp.class ),
|
||||||
|
calendarArgumentCaptor.capture()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
TIME_ZONE,
|
||||||
|
calendarArgumentCaptor.getValue().getTimeZone()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
fail( e.getMessage() );
|
||||||
|
}
|
||||||
|
|
||||||
|
connectionProvider.clear();
|
||||||
|
doInHibernateSessionBuilder( () -> {return sessionFactory().withOptions().jdbcTimeZone( TIME_ZONE);}, s -> {
|
||||||
|
s.doWork( connection -> {
|
||||||
|
try (Statement st = connection.createStatement()) {
|
||||||
|
try (ResultSet rs = st.executeQuery(
|
||||||
|
"select createdOn from Person" )) {
|
||||||
|
while ( rs.next() ) {
|
||||||
|
Timestamp timestamp = rs.getTimestamp( 1 );
|
||||||
|
int offsetDiff = TimeZone.getDefault()
|
||||||
|
.getOffset( 0 ) - TIME_ZONE.getOffset( 0 );
|
||||||
|
assertEquals(
|
||||||
|
Math.abs( Long.valueOf( offsetDiff )
|
||||||
|
.longValue() ),
|
||||||
|
Math.abs( timestamp.getTime() )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
Person person = s.find( Person.class, 1L );
|
||||||
|
assertEquals( 0, person.createdOn.getTime() );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Person")
|
||||||
|
public static class Person {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private Timestamp createdOn = new Timestamp( 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
* 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.timestamp;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.hibernate.test.util.jdbc.PreparedStatementSpyConnectionProvider;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.anyInt;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class JdbcTimestampCustomTimeZoneTest
|
||||||
|
extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider();
|
||||||
|
|
||||||
|
private static final TimeZone TIME_ZONE = TimeZone.getTimeZone(
|
||||||
|
"America/Los_Angeles" );
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Person.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addSettings(Map settings) {
|
||||||
|
settings.put(
|
||||||
|
AvailableSettings.CONNECTION_PROVIDER,
|
||||||
|
connectionProvider
|
||||||
|
);
|
||||||
|
settings.put(
|
||||||
|
AvailableSettings.JDBC_TIME_ZONE,
|
||||||
|
TIME_ZONE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void releaseResources() {
|
||||||
|
super.releaseResources();
|
||||||
|
connectionProvider.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTimeZone() {
|
||||||
|
|
||||||
|
connectionProvider.clear();
|
||||||
|
doInHibernate( this::sessionFactory, s -> {
|
||||||
|
Person person = new Person();
|
||||||
|
person.id = 1L;
|
||||||
|
s.persist( person );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
assertEquals( 1, connectionProvider.getPreparedStatements().size() );
|
||||||
|
PreparedStatement ps = connectionProvider.getPreparedStatements()
|
||||||
|
.get( 0 );
|
||||||
|
try {
|
||||||
|
ArgumentCaptor<Calendar> calendarArgumentCaptor = ArgumentCaptor.forClass(
|
||||||
|
Calendar.class );
|
||||||
|
verify( ps, times( 1 ) ).setTimestamp(
|
||||||
|
anyInt(),
|
||||||
|
any( Timestamp.class ),
|
||||||
|
calendarArgumentCaptor.capture()
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
TIME_ZONE,
|
||||||
|
calendarArgumentCaptor.getValue().getTimeZone()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
fail( e.getMessage() );
|
||||||
|
}
|
||||||
|
|
||||||
|
connectionProvider.clear();
|
||||||
|
doInHibernate( this::sessionFactory, s -> {
|
||||||
|
s.doWork( connection -> {
|
||||||
|
try (Statement st = connection.createStatement()) {
|
||||||
|
try (ResultSet rs = st.executeQuery(
|
||||||
|
"select createdOn from Person" )) {
|
||||||
|
while ( rs.next() ) {
|
||||||
|
Timestamp timestamp = rs.getTimestamp( 1 );
|
||||||
|
int offsetDiff = TimeZone.getDefault()
|
||||||
|
.getOffset( 0 ) - TIME_ZONE.getOffset( 0 );
|
||||||
|
assertEquals(
|
||||||
|
Math.abs( Long.valueOf( offsetDiff )
|
||||||
|
.longValue() ),
|
||||||
|
Math.abs( timestamp.getTime() )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
Person person = s.find( Person.class, 1L );
|
||||||
|
assertEquals( 0, person.createdOn.getTime() );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Person")
|
||||||
|
public static class Person {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private Timestamp createdOn = new Timestamp( 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
* 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.timestamp;
|
||||||
|
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.hibernate.test.util.jdbc.PreparedStatementSpyConnectionProvider;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.fail;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.anyInt;
|
||||||
|
import static org.mockito.Mockito.times;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class JdbcTimestampDefaultTimeZoneTest
|
||||||
|
extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Person.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addSettings(Map settings) {
|
||||||
|
settings.put(
|
||||||
|
AvailableSettings.CONNECTION_PROVIDER,
|
||||||
|
connectionProvider
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void releaseResources() {
|
||||||
|
super.releaseResources();
|
||||||
|
connectionProvider.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTimeZone() {
|
||||||
|
|
||||||
|
connectionProvider.clear();
|
||||||
|
doInHibernate( this::sessionFactory, s -> {
|
||||||
|
Person person = new Person();
|
||||||
|
person.id = 1L;
|
||||||
|
s.persist( person );
|
||||||
|
|
||||||
|
} );
|
||||||
|
|
||||||
|
assertEquals( 1, connectionProvider.getPreparedStatements().size() );
|
||||||
|
PreparedStatement ps = connectionProvider.getPreparedStatements()
|
||||||
|
.get( 0 );
|
||||||
|
try {
|
||||||
|
verify( ps, times( 1 ) ).setTimestamp(
|
||||||
|
anyInt(),
|
||||||
|
any( Timestamp.class )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (SQLException e) {
|
||||||
|
fail( e.getMessage() );
|
||||||
|
}
|
||||||
|
|
||||||
|
doInHibernate( this::sessionFactory, s -> {
|
||||||
|
Person person = s.find( Person.class, 1L );
|
||||||
|
assertEquals( 0, person.createdOn.getTime() );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Person")
|
||||||
|
public static class Person {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private Timestamp createdOn = new Timestamp( 0 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
* 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.timestamp;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.dialect.PostgreSQL82Dialect;
|
||||||
|
|
||||||
|
import org.hibernate.testing.RequiresDialect;
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.hibernate.test.util.jdbc.PreparedStatementSpyConnectionProvider;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
@RequiresDialect( value = PostgreSQL82Dialect.class)
|
||||||
|
public class JdbcTimestampUTCTimeZoneTest
|
||||||
|
extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
private PreparedStatementSpyConnectionProvider connectionProvider = new PreparedStatementSpyConnectionProvider();
|
||||||
|
|
||||||
|
private static final TimeZone TIME_ZONE = TimeZone.getTimeZone( "UTC" );
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Person.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addSettings(Map settings) {
|
||||||
|
settings.put(
|
||||||
|
AvailableSettings.CONNECTION_PROVIDER,
|
||||||
|
connectionProvider
|
||||||
|
);
|
||||||
|
settings.put(
|
||||||
|
AvailableSettings.JDBC_TIME_ZONE,
|
||||||
|
TIME_ZONE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void releaseResources() {
|
||||||
|
super.releaseResources();
|
||||||
|
connectionProvider.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTimeZone() {
|
||||||
|
|
||||||
|
connectionProvider.clear();
|
||||||
|
doInHibernate( this::sessionFactory, s -> {
|
||||||
|
Person person = new Person();
|
||||||
|
person.id = 1L;
|
||||||
|
//Y2K
|
||||||
|
person.createdOn = new Timestamp(946684800000L);
|
||||||
|
s.persist( person );
|
||||||
|
|
||||||
|
} );
|
||||||
|
doInHibernate( this::sessionFactory, s -> {
|
||||||
|
Person person = s.find( Person.class, 1L );
|
||||||
|
assertEquals( 946684800000L, person.createdOn.getTime() );
|
||||||
|
s.doWork( connection -> {
|
||||||
|
try (Statement st = connection.createStatement()) {
|
||||||
|
try (ResultSet rs = st.executeQuery(
|
||||||
|
"SELECT " +
|
||||||
|
" to_char(createdon, 'YYYY-MM-DD HH24:MI:SS.US') " +
|
||||||
|
"FROM person" )) {
|
||||||
|
while ( rs.next() ) {
|
||||||
|
String timestamp = rs.getString( 1 );
|
||||||
|
assertEquals("2000-01-01 00:00:00.000000", timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Person")
|
||||||
|
public static class Person {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private Timestamp createdOn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* 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.timestamp;
|
||||||
|
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.sql.Timestamp;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.dialect.PostgreSQL82Dialect;
|
||||||
|
|
||||||
|
import org.hibernate.testing.RequiresDialect;
|
||||||
|
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||||
|
import org.hibernate.test.util.jdbc.TimeZoneConnectionProvider;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
@RequiresDialect( value = PostgreSQL82Dialect.class)
|
||||||
|
public class JdbcTimestampWithoutUTCTimeZoneTest
|
||||||
|
extends BaseNonConfigCoreFunctionalTestCase {
|
||||||
|
|
||||||
|
private TimeZoneConnectionProvider connectionProvider = new TimeZoneConnectionProvider( "America/Los_Angeles" );
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Person.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void addSettings(Map settings) {
|
||||||
|
settings.put(
|
||||||
|
AvailableSettings.CONNECTION_PROVIDER,
|
||||||
|
connectionProvider
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void releaseResources() {
|
||||||
|
super.releaseResources();
|
||||||
|
connectionProvider.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTimeZone() {
|
||||||
|
doInHibernate( this::sessionFactory, s -> {
|
||||||
|
Person person = new Person();
|
||||||
|
person.id = 1L;
|
||||||
|
//Y2K
|
||||||
|
person.createdOn = new Timestamp(946684800000L);
|
||||||
|
s.persist( person );
|
||||||
|
|
||||||
|
} );
|
||||||
|
doInHibernate( this::sessionFactory, s -> {
|
||||||
|
s.doWork( connection -> {
|
||||||
|
try (Statement st = connection.createStatement()) {
|
||||||
|
try (ResultSet rs = st.executeQuery(
|
||||||
|
"SELECT " +
|
||||||
|
" to_char(createdon, 'YYYY-MM-DD HH24:MI:SS.US') " +
|
||||||
|
"FROM person" )) {
|
||||||
|
while ( rs.next() ) {
|
||||||
|
String timestamp = rs.getString( 1 );
|
||||||
|
assertEquals("1999-12-31 16:00:00.000000", timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Person")
|
||||||
|
public static class Person {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private Timestamp createdOn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,13 +8,13 @@ package org.hibernate.test.timestamp;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
import org.hibernate.cfg.Configuration;
|
import org.hibernate.cfg.Configuration;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,10 @@ import java.sql.Clob;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.util.TimeZone;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import org.hibernate.engine.jdbc.LobCreator;
|
import org.hibernate.engine.jdbc.LobCreator;
|
||||||
import org.hibernate.engine.jdbc.NonContextualLobCreator;
|
import org.hibernate.engine.jdbc.NonContextualLobCreator;
|
||||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
|
||||||
import org.hibernate.type.descriptor.ValueBinder;
|
import org.hibernate.type.descriptor.ValueBinder;
|
||||||
import org.hibernate.type.descriptor.ValueExtractor;
|
import org.hibernate.type.descriptor.ValueExtractor;
|
||||||
import org.hibernate.type.descriptor.WrapperOptions;
|
import org.hibernate.type.descriptor.WrapperOptions;
|
||||||
|
@ -23,6 +21,9 @@ import org.hibernate.type.descriptor.sql.ClobTypeDescriptor;
|
||||||
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||||
import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor;
|
import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor;
|
||||||
|
|
||||||
|
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
|
|
||||||
|
@ -47,6 +48,11 @@ public class StringValueMappingTest extends BaseUnitTestCase {
|
||||||
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
|
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
|
||||||
return sqlTypeDescriptor;
|
return sqlTypeDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeZone getJdbcTimeZone() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final String COLUMN_NAME = "n/a";
|
public static final String COLUMN_NAME = "n/a";
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package org.hibernate.test.util;
|
package org.hibernate.test.util;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vlad Mihalcea
|
* @author Vlad Mihalcea
|
||||||
|
@ -24,6 +27,26 @@ public class ReflectionUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a field value from a given object
|
||||||
|
* @param target Object whose field is being read
|
||||||
|
* @param name field name
|
||||||
|
* @return field object
|
||||||
|
*/
|
||||||
|
public static <T> T getFieldValue(Object target, String name) {
|
||||||
|
try {
|
||||||
|
Field field = target.getClass().getDeclaredField( name );
|
||||||
|
field.setAccessible( true );
|
||||||
|
return (T) field.get( target );
|
||||||
|
}
|
||||||
|
catch ( NoSuchFieldException e ) {
|
||||||
|
throw new IllegalArgumentException( "Class " + target.getClass() + " does not contain a " + name + " field", e);
|
||||||
|
}
|
||||||
|
catch ( IllegalAccessException e ) {
|
||||||
|
throw new IllegalArgumentException( "Cannot set field " + name, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set target Object field to a certain value
|
* Set target Object field to a certain value
|
||||||
* @param target Object whose field is being set
|
* @param target Object whose field is being set
|
||||||
|
@ -38,4 +61,37 @@ public class ReflectionUtil {
|
||||||
throw new IllegalArgumentException("Field " + field + " could not be set", e );
|
throw new IllegalArgumentException("Field " + field + " could not be set", e );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New target Object instance using the given arguments
|
||||||
|
* @param constructorSupplier constructor supplier
|
||||||
|
* @param args Constructor arguments
|
||||||
|
* @return new Object instance
|
||||||
|
*/
|
||||||
|
public static <T> T newInstance(Supplier<Constructor<T>> constructorSupplier, Object... args) {
|
||||||
|
try {
|
||||||
|
Constructor constructor = constructorSupplier.get();
|
||||||
|
constructor.setAccessible( true );
|
||||||
|
return (T) constructor.newInstance( args );
|
||||||
|
}
|
||||||
|
catch ( IllegalAccessException | InstantiationException | InvocationTargetException e ) {
|
||||||
|
throw new IllegalArgumentException("Constructor could not be called", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set target Object field to a certain value
|
||||||
|
* @param target Object whose field is being set
|
||||||
|
* @param fieldName Object field naem to set
|
||||||
|
* @param value the new value for the given field
|
||||||
|
*/
|
||||||
|
public static void setField(Object target, String fieldName, Object value) {
|
||||||
|
try {
|
||||||
|
Field field = getField(target.getClass(), fieldName);
|
||||||
|
field.set( target, value );
|
||||||
|
}
|
||||||
|
catch ( IllegalAccessException e ) {
|
||||||
|
throw new IllegalArgumentException("Field " + fieldName + " could not be set", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* 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.util.jdbc;
|
||||||
|
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This {@link ConnectionProvider} extends any other ConnectionProvider that would be used by default taken the current configuration properties, and it
|
||||||
|
* just sets a default TimeZone which is different than the current default one.
|
||||||
|
*
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class TimeZoneConnectionProvider
|
||||||
|
extends ConnectionProviderDelegate {
|
||||||
|
|
||||||
|
private final String defaultTimeZone;
|
||||||
|
private final String customTimeZone;
|
||||||
|
|
||||||
|
public TimeZoneConnectionProvider(String customTimeZone) {
|
||||||
|
this.customTimeZone = customTimeZone;
|
||||||
|
this.defaultTimeZone = System.setProperty( "user.timezone", customTimeZone);
|
||||||
|
TimeZone.setDefault(TimeZone.getTimeZone( customTimeZone ));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
super.stop();
|
||||||
|
System.setProperty( "user.timezone", defaultTimeZone);
|
||||||
|
TimeZone.setDefault(TimeZone.getTimeZone( defaultTimeZone ));
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,6 +14,7 @@ import javax.persistence.EntityManagerFactory;
|
||||||
import javax.persistence.EntityTransaction;
|
import javax.persistence.EntityTransaction;
|
||||||
|
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.SessionBuilder;
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
|
|
||||||
|
@ -183,7 +184,7 @@ public class TransactionUtil {
|
||||||
/**
|
/**
|
||||||
* Execute function in a Hibernate transaction
|
* Execute function in a Hibernate transaction
|
||||||
*
|
*
|
||||||
* @param factorySupplier EntityManagerFactory supplier
|
* @param factorySupplier SessionFactory supplier
|
||||||
* @param function function
|
* @param function function
|
||||||
* @param <T> result type
|
* @param <T> result type
|
||||||
*
|
*
|
||||||
|
@ -219,9 +220,9 @@ public class TransactionUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute function in a JPA transaction without return value
|
* Execute function in a Hibernate transaction without return value
|
||||||
*
|
*
|
||||||
* @param factorySupplier EntityManagerFactory supplier
|
* @param factorySupplier SessionFactory supplier
|
||||||
* @param function function
|
* @param function function
|
||||||
*/
|
*/
|
||||||
public static void doInHibernate(
|
public static void doInHibernate(
|
||||||
|
@ -250,4 +251,75 @@ public class TransactionUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute function in a Hibernate transaction
|
||||||
|
*
|
||||||
|
* @param sessionBuilderSupplier SessionFactory supplier
|
||||||
|
* @param function function
|
||||||
|
* @param <T> result type
|
||||||
|
*
|
||||||
|
* @return result
|
||||||
|
*/
|
||||||
|
public static <T> T doInHibernateSessionBuilder(
|
||||||
|
Supplier<SessionBuilder> sessionBuilderSupplier,
|
||||||
|
HibernateTransactionFunction<T> function) {
|
||||||
|
T result = null;
|
||||||
|
Session session = null;
|
||||||
|
Transaction txn = null;
|
||||||
|
try {
|
||||||
|
session = sessionBuilderSupplier.get().openSession();
|
||||||
|
function.beforeTransactionCompletion();
|
||||||
|
txn = session.beginTransaction();
|
||||||
|
|
||||||
|
result = function.apply( session );
|
||||||
|
txn.commit();
|
||||||
|
}
|
||||||
|
catch ( Throwable e ) {
|
||||||
|
if ( txn != null ) {
|
||||||
|
txn.rollback();
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
function.afterTransactionCompletion();
|
||||||
|
if ( session != null ) {
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute function in a Hibernate transaction without return value
|
||||||
|
*
|
||||||
|
* @param sessionBuilderSupplier SessionFactory supplier
|
||||||
|
* @param function function
|
||||||
|
*/
|
||||||
|
public static void doInHibernateSessionBuilder(
|
||||||
|
Supplier<SessionBuilder> sessionBuilderSupplier,
|
||||||
|
HibernateTransactionConsumer function) {
|
||||||
|
Session session = null;
|
||||||
|
Transaction txn = null;
|
||||||
|
try {
|
||||||
|
session = sessionBuilderSupplier.get().openSession();
|
||||||
|
function.beforeTransactionCompletion();
|
||||||
|
txn = session.beginTransaction();
|
||||||
|
|
||||||
|
function.accept( session );
|
||||||
|
txn.commit();
|
||||||
|
}
|
||||||
|
catch ( Throwable e ) {
|
||||||
|
if ( txn != null ) {
|
||||||
|
txn.rollback();
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
function.afterTransactionCompletion();
|
||||||
|
if ( session != null ) {
|
||||||
|
session.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue