yyyy variable tipo obtener ingresar hora fechas fecha declarar dato clase actual java sql hibernate timestamp

variable - ¿Qué zona horaria usa Hibernate cuando lee y escribe un objeto Java Calendar en un SQL TIMESTAMP?



tipo de dato hora en java (4)

Cuando Hibernate escribe un objeto de calendario Java en una columna de TIMESTAMP de SQL, ¿en qué zona horaria ajusta la fecha, la de la computadora o la especificada en el objeto de calendario (o algún otro)?

Hiberante 3.x usa lo siguiente en el Tipo de CalendarType (ver HB-1006 ):

public void set(PreparedStatement st, Object value, int index) throws HibernateException, SQLException { final Calendar cal = (Calendar) value; //st.setTimestamp( index, new Timestamp( cal.getTimeInMillis() ), cal ); //JDK 1.5 only st.setTimestamp( index, new Timestamp( cal.getTime().getTime() ), cal ); }

Así que Hibernate usa PreparedStatement#setTimestamp(int, Timestamp, Calendar) que usa la zona horaria del calendario.

Cuando Hibernate lee el TIMESTAMP en el objeto del calendario, ¿a qué zona horaria se traduce la fecha?

Bueno, una vez más, veamos la clase CalendarType :

public Object get(ResultSet rs, String name) throws HibernateException, SQLException { Timestamp ts = rs.getTimestamp(name); if (ts!=null) { Calendar cal = new GregorianCalendar(); if ( Environment.jvmHasTimestampBug() ) { cal.setTime( new Date( ts.getTime() + ts.getNanos() / 1000000 ) ); } else { cal.setTime(ts); } return cal; } else { return null; } }

Así que Hibernate construye un GregorianCalendar predeterminado usando la hora actual en la zona horaria predeterminada con la configuración regional predeterminada .

Como nota al margen, sugiero encarecidamente leer la siguiente pregunta:

Cuando Hibernate escribe un objeto de Calendar Java en una columna de TIMESTAMP SQL, ¿en qué zona horaria ajusta la fecha, la de la computadora o la especificada en el objeto de calendario (o algún otro)?

Cuando Hibernate lee el TIMESTAMP en el objeto del calendario, ¿a qué zona horaria se traduce la fecha?


Acabo de pasar 6 horas en un problema similar y pensé en documentarlo aquí. De hecho, Hibernate usa la zona horaria JVM pero puede cambiarse extendiendo el Tipo de Calendario de esta manera:

public class UTCCalendarType extends CalendarType { private static final TimeZone UTC = TimeZone.getTimeZone("UTC"); /** * This is the original code from the class, with two changes. First we pull * it out of the result set with an example Calendar. Second, we set the new * calendar up in UTC. */ @Override public Object get(ResultSet rs, String name) throws SQLException { Timestamp ts = rs.getTimestamp(name, new GregorianCalendar(UTC)); if (ts != null) { Calendar cal = new GregorianCalendar(UTC); cal.setTime(ts); return cal; } else { return null; } } @Override public void set(PreparedStatement st, Object value, int index) throws SQLException { final Calendar cal = (Calendar) value; cal.setTimeZone(UTC); st.setTimestamp(index, new Timestamp(cal.getTime().getTime()), cal); } }

La salsa secreta aquí es:

rs.getTimestamp(name, new GregorianCalendar(UTC));

Esto convierte la zona horaria del conjunto de resultados a la zona horaria que desee. Entonces, lo que hice fue usar este tipo con cualquier calendario UTC y el tipo de Hibernate estándar para la hora local. Funciona bien como un silbato ...


De forma predeterminada, depende del controlador JDBC decidir qué zona horaria usar. Normalmente, la zona horaria JVM se usa a menos que configure el controlador JDBC para usar una zona horaria personalizada.

Si desea controlar qué zona horaria se utiliza, puede configurar la zona horaria en el nivel JVM. Si desea que la zona horaria de la JVM sea diferente de la utilizada por la base de datos, debe utilizar la siguiente propiedad de configuración de Hibernate 5.2:

<property name="hibernate.jdbc.time_zone" value="US/Eastern"/>

Para más detalles, echa un vistazo a este artículo .


Si no desea escribir el código usted mismo, solo puede usar la biblioteca de código abierto DbAssist . Después de aplicar esta revisión, las fechas en la base de datos serán tratadas por JDBC y luego por Hibernate como UTC, por lo que ni siquiera tendrá que cambiar sus clases de entidad.

Por ejemplo, si está usando anotaciones JPA con Hibernate 4.3.11, agregue la siguiente dependencia de Maven:

<dependency> <groupId>com.montrosesoftware</groupId> <artifactId>DbAssist-4.3.11</artifactId> <version>1.0-RELEASE</version> </dependency>

Entonces simplemente aplique la solución:

Para la configuración de Hibernate + Spring Boot, agregue la anotación @EnableAutoConfiguration antes de la clase de la aplicación.

Para los archivos HBM, tiene que cambiar los archivos de mapeo de la entidad para asignar los tipos de Date al personalizado:

<property name="createdAt" type="com.montrosesoftware.dbassist.types.UtcDateType" column="created_at"/>

Si desea obtener más información sobre cómo aplicar la corrección para diferentes versiones de Hibernate (o archivos HBM), consulte el github del proyecto . También puede leer más sobre el problema del cambio de zona horaria en este article .