Microsoft SQL JDBC 驱动程序 v6.2 为 DATETIME 字段返回不正确的 SQL 类型代码
Microsoft SQL JDBC driver v6.2 returning incorrect SQL type code for DATETIME fields
通常,ResultSetMetaData#getColumnType()
should return 93
用于 DATETIME
个字段(通常表示为 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 特别是)与 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 服务器版本(如 2014)不会出现上述问题。
SQL Server Management Studio 2014 始终正确报告列类型 (DATETIME
),无论它连接到的服务器版本如何。
JDBC 驱动程序有什么问题?微软是否再次打破了与自己产品之一的兼容性?
"Has Microsoft once again broken compatibility with one of its own products?"
从技术上讲,不,因为 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.
通常,ResultSetMetaData#getColumnType()
should return 93
用于 DATETIME
个字段(通常表示为 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 特别是)与 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 服务器版本(如 2014)不会出现上述问题。
SQL Server Management Studio 2014 始终正确报告列类型 (DATETIME
),无论它连接到的服务器版本如何。
JDBC 驱动程序有什么问题?微软是否再次打破了与自己产品之一的兼容性?
"Has Microsoft once again broken compatibility with one of its own products?"
从技术上讲,不,因为 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.