java - Microsoft SQL JDBC 驱动程序 v6.2 为 DATETIME 字段返回不正确的 SQL 类型代码

标签 java sql-server jdbc sql-server-2005 mssql-jdbc

通常,ResultSetMetaData#getColumnType()应该返回 93对于 DATETIME 字段(通常表示为 java.sql.Timestamp)。

对于驱动程序版本 4.2.6420.1004.0.4621.201(以及 jTDS)确实如此。

在 Microsoft SQL Server 2005 中使用较新的 Microsoft JDBC 驱动程序(6.0.7728.1006.0.8112.1006.2.1.0)时(9.0.1399),我观察到返回了一个不同的类型代码:-151,它甚至没有映射到 java.sql.Types 中的任何类型。

同时,ResultSetMetaData#g​​etColumnClassName(int)ResultSetMetaData#g​​etColumnTypeName(int) 行为正确(始终返回 java.sql.Timestampdatetime)。

这是使用上述驱动程序和服务器组合运行时失败的单元测试:

package com.example;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;

import javax.sql.DataSource;

import org.eclipse.jdt.annotation.Nullable;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import com.microsoft.sqlserver.jdbc.SQLServerConnectionPoolDataSource;

public final class MsSqlServerTest {
    @Nullable
    private static DataSource dataSource;

    @Nullable
    private Connection conn;

    @BeforeClass
    public static void setUpOnce() {
        dataSource = new SQLServerConnectionPoolDataSource();
        ((SQLServerConnectionPoolDataSource) dataSource).setURL("jdbc:sqlserver://localhost\\SQLEXPRESS:1433;databaseName=...");
    }

    @BeforeMethod
    public void setUp() throws SQLException {
        this.conn = dataSource.getConnection("...", "...");
    }

    @AfterMethod
    public void tearDown() throws SQLException {
        if (this.conn != null) {
            this.conn.close();
        }
        this.conn = null;
    }

    @Test
    public void testDateTimeCode() throws SQLException {
        try (final Statement stmt = this.conn.createStatement()) {
            try {
                stmt.executeUpdate("drop table test");
            } catch (@SuppressWarnings("unused") final SQLException ignored) {
                // ignore
            }
            stmt.executeUpdate("create table test (value datetime)");

            try (final ResultSet rset = stmt.executeQuery("select * from test")) {
                final ResultSetMetaData metaData = rset.getMetaData();
                assertThat(metaData.getColumnClassName(1), is(java.sql.Timestamp.class.getName()));
                assertThat(metaData.getColumnTypeName(1), is("datetime"));
                assertThat(metaData.getColumnType(1), is(Types.TIMESTAMP));
            }
        }
    }
}

较新的 Microsoft SQL Server 版本(如 2014)不会出现上述问题。

SQL Server Management Studio 2014 始终正确报告列类型(DATETIME),无论它连接到的服务器版本如何。

JDBC 驱动有什么问题?微软是否再次破坏了与其产品之一的兼容性?

最佳答案

“微软是否再次打破了与自己产品之一的兼容性?”

从技术上讲,不,因为当前版本的 JDBC 驱动程序不支持 SQL Server 2005。根据 SQL Server requirements对于 JDBC 驱动程序:

For Microsoft JDBC Driver 4.2 and 4.1 for SQL Server, support begins with SQL Server 2008. For Microsoft JDBC Driver 4.0 for SQL Server, support beings [sic] with SQL Server 2005.

这也是 discussed on GitHub .

关于java - Microsoft SQL JDBC 驱动程序 v6.2 为 DATETIME 字段返回不正确的 SQL 类型代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45377247/

相关文章:

Java slick statebased game - 状态返回空点错误

java - Jmap堆转储,它包括年轻一代吗?

sql - 为什么插入和加入#temp 表更快?

sql - 当月的第一个工作日 - SQL Server

java - 将数据库连接到另一台计算机

java - 如何在 Java 程序中访问 SQL count() 查询的值

Java写入文件排序数组

java - XML 字符串转换

python - 使用 PYODBC 和 FreeTDS 从 SQL Server 检索记录

java - 用 Java 处理数百万条数据库记录