数据库
首页 > 数据库> > java – Microsoft SQL JDBC驱动程序v6.2为DATETIME字段返回不正确的SQL类型代码

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

作者:互联网

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

对于驱动程序版本4.2.6420.100和4.0.4621.201(以及jTDS)确实如此.

当使用较新的Microsoft JDBC驱动程序(6.0.7728.100,6.0.8112.100和6.2.1.0 in partucular)与Microsoft SQL Server 2005(9.0.1399)时,我发现返回了不同的类型代码:-151,它甚至没有映射到java.sql.Types中的任何类型.

同时,ResultSetMetaData#getColumnClassName(int)和ResultSetMetaData#getColumnTypeName(int)的行为正确(始终分别返回java.sql.Timestamp和datetime).

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

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.根据JDBC驱动程序的SQL Server requirements

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,sql-server,sql-server-2005,jdbc,mssql-jdbc
来源: https://codeday.me/bug/20190701/1349434.html