LocalDateTime y SQL Server JDBC 4.2 controlador

Krzysztof:

Estoy tratando de utilizar las nuevas java.timeclases con más reciente versión del controlador JDBC de SQL Server. Mientras lo leía simplemente debe trabajar con métodos: PreparedStatement.setObject()e ResultSet.getObject().

Así que creé código de ejemplo, y no lo puede operar con conjuntos de resultados. No sé lo que estoy haciendo mal aquí.

Connection connection = DriverManager.getConnection(connectionString);
PreparedStatement preparedStatement = connection.prepareStatement("SELECT * FROM myTable WHERE ? BETWEEN date_from AND date_to");
preparedStatement.setObject(1, LocalDateTime.now());   // That works

ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
    Object o = resultSet.getObject("date_from"); 
    o.getClass() returns java.sql.Timestamp

    LocalDateTime dateTime = resultSet.getObject("date_from", LocalDateTime.class);
}

Esto arroja una excepción:

com.microsoft.sqlserver.jdbc.SQLServerException: La conversión a la clase java.time.LocalDateTime no es compatible.

versión del controlador: mssql-JDBC-6.5.4.jre8-preview.jar

Versión de servidor SQL: 2016


https://docs.microsoft.com/en-us/sql/connect/jdbc/jdbc-4-2-compliance-for-the-jdbc-driver?view=sql-server-2017

¿Cómo interpretar esta frase en el cuadro en la parte inferior:

Nuevas clases de Java en Java 8: LocalDate / LocalTime / LocalDateTime, OffsetTime / OffsetDateTime

Nuevos tipos de JDBC: TIME_WITH_TIMEZONE, TIMESTAMP_WITH_TIMEZONE, REF_CURSOR

REF_CURSOR is not supported in SQL Server. Driver throws a SQLFeatureNotSupportedException exception if this type is used. The driver supports all other new Java and JDBC type mappings as specified in the JDBC 4.2 specification.

Gord Thompson:

No sé lo que estoy haciendo mal aquí.

No estás haciendo mal nada. Se ha encontrado con una deficiencia en el controlador JDBC de Microsoft para SQL Server antes de la versión 7.1.0 , discutido aquí .

Si está utilizando JDBC-mssql versión 7.1.0 o posterior, puede utilizar getObject(x, LocalDateTime.class)como se esperaba.

Para las versiones de MSSQL-JDBC anteriores a 7.1.0, como otros han sugerido, que necesita para recuperar una Timestampy convertirlo en una LocalDateTime. Sin embargo, tenga en cuenta que la solución simplista ...

LocalDateTime dateTime = resultSet.getTimestamp("date_from").toLocalDateTime()

... corromperá ciertos valores de fecha / hora, si la zona horaria predeterminada para la JVM observa el horario de verano, también conocido como "tiempo de verano". Por ejemplo,

// time zone with Daylight Time
TimeZone.setDefault(TimeZone.getTimeZone("America/Edmonton"));

// test environment
Statement st = conn.createStatement();
st.execute("CREATE TABLE #tmp (id INT PRIMARY KEY, dt2 DATETIME2)");
st.execute("INSERT INTO #tmp (id, dt2) VALUES (1, '2018-03-11 02:00:00')");
ResultSet rs = st.executeQuery("SELECT dt2 FROM #tmp WHERE id=1");
rs.next();

// test code
LocalDateTime x = rs.getTimestamp("dt2").toLocalDateTime();  // bad

System.out.println(x.toString());

imprimirá "2018-03-11T03: 00". Tenga en cuenta que el tiempo es "03:00", no "02:00".

En su lugar, tendrá que recuperar el Timestampcomo UTC y luego convertirlo en una LocalDateTimede UTC, eliminando así el componente de zona horaria

// time zone with Daylight Time
TimeZone.setDefault(TimeZone.getTimeZone("America/Edmonton"));

// test environment
Statement st = conn.createStatement();
st.execute("CREATE TABLE #tmp (id INT PRIMARY KEY, dt2 DATETIME2)");
st.execute("INSERT INTO #tmp (id, dt2) VALUES (1, '2018-03-11 02:00:00')");
ResultSet rs = st.executeQuery("SELECT dt2 FROM #tmp WHERE id=1");
rs.next();

// test code
Timestamp ts = getTimestamp("dt2", Calendar.getInstance(TimeZone.getTimeZone("UTC")));
LocalDateTime x = LocalDateTime.ofInstant(ts.toInstant(), ZoneId.of("UTC"));  // good

System.out.println(x.toString());

que imprime "2018-03-11T02: 00".

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=190563&siteId=1
Recomendado
Clasificación