JDBC 配置和故障排除

本文介绍 Java 数据库连接(JDBC)和配置过程中发生的故障排除步骤。 重点是 JDBC for SQL Server。

注意

  • 本文基于 C 驱动器根目录中安装的最新 JDBC 驱动程序(版本 12.4)。
  • Microsoft不会排查存在第三方连接池管理器的 JDBC 连接问题。 使用第三方连接池管理器进行故障排除有可能公开知识产权信息。

用于 SQL Server 的 Microsoft JDBC 驱动程序

本文提供了 JDBC 的参考指南,包括驱动程序和支持文档、不同操作系统(OS)的安装说明以及 SQL Server 连接问题疑难解答。

JDBC 驱动程序版本更改

JDBC 要求

  • Java 运行时环境 (JRE) 版本必须与驱动程序与名称中指定的 JRE 版本匹配。 例如,mssql-jdbc-9.4.1.jre8.jar需要 JRE 1.8,mssql-jdbc-9.4.1.jre11.jar需要 JRE 11.0。

  • CLASSPATH 是一个 Java 环境变量,其中包含目录路径和二进制 jar 文件。 Java 需要它来执行所需的应用程序。 需要指定哪些驱动程序和依赖项二进制 jar 文件 Java 需要运行。 最小值 CLASSPATH 包括当前工作目录 .; 和 JDBC 驱动程序 jar 文件的位置。

JDBC 配置和故障排除步骤

设置 CLASSPATH 变量

CLASSPATHs 可以在 OS 环境变量或应用程序环境本身(如 Tomcat)中定义。 如果在 CLASSPATH 应用程序环境中定义,则应用程序供应商或开发人员必须参与,以确保 CLASSPATH 正确配置到位。

若要设置 CLASSPATH,请使用以下方法之一:

注意

命令提示符设置是临时的,关闭命令提示符窗口时将被删除。 图形用户界面(GUI)是永久设置,需要重新启动。

命令提示符示例

Set CLASSPATH=.;C:\sqljdbc_12.4\enu\mssql-jdbc-12.4.0.jre8.jar

GUI 示例

若要使用 GUI 进行设置 CLASSPATH ,请执行以下步骤:

  1. 打开控制面板并选择“系统和安全性”。

  2. 选择 系统>高级系统设置

  3. 选择“环境变量>新建,然后输入 CLASSPATH 作为变量名称。

  4. 选择“编辑并输入 .;C:\sqljdbc_12.4\enu\mssql-jdbc-12.4.0.jre8.jar作为变量值。

  5. 选择“确定”

具有传入凭据的连接字符串

具有传入凭据的连接字符串是指将身份验证凭据(如用户名和密码)作为字符串中的参数或值连接字符串。 当程序连接到数据库或其他服务时,需要提供身份验证信息来建立安全连接。

以下连接字符串演示了如何基于要使用的身份验证模式连接到 SQL Server 数据库的示例:

SQL Server 身份验证

连接字符串为 String connectionUrl = "jdbc:sqlserver://<ServerName>:<PortNum>;user=<MySQLAuthAccount>;password=<MyPassword>;trustServerCertificate=true;"

没有集成安全性的 Windows AD 身份验证

连接字符串为 String connectionUrl = "jdbc:sqlserver://<ServerName>:<PortNum>;user=<MyADAuthAccount>;password=<MyPassword>;Domain=<MyDomain>;trustServerCertificate=true;javaAuthentication=NTLM"

使用 Kerberos 和没有集成安全性的 Windows AD 身份验证

连接字符串为 String connectionUrl = "jdbc:sqlserver://<ServerName>:<PortNum>;user=<MyADAuthAccount>;password=<MyPassword>;Domain=<MyDomain>;trustServerCertificate=true;javaAuthentication=JavaKerberos"

集成 NTLM 连接

在此类连接中,客户端计算机必须位于 Windows 域中。

mssql-jdbc_auth-version-arch<><>.dll 文件必须位于以下路径中:

  • 64 位 DLL

    %Path%;C:\sqljdbc_12.4.1.0_enu\sqljdbc_12.4\enu\auth\x64\mssql-jdbc_auth-12.4.1.x64.dll

  • 32 位 DLL

    %Path%;C:\sqljdbc_12.4.1.0_enu\sqljdbc_12.4\enu\auth\x86\mssql-jdbc_auth-12.4.1.x86.dll

可以修改并添加路径,也可以将文件复制到已建立的路径中。 有关详细信息,请参阅 在 Windows 上使用集成身份验证进行连接。

连接字符串为 String connectionUrl = "jdbc:sqlserver://<ServerName>:<PortNum>;integratedSecurity=true;Domain=<MyDomain>;trustServerCertificate=true;javaAuthentication=NTLM"

集成的 Kerberos 连接

此类型的连接的先决条件包括:

  • 必须是域的一部分。
  • 必须在 Linux OS 上安装和配置 SSSD。
  • 必须在 Linux OS 上安装并配置 Klist。

mssql-jdbc_auth-version-arch<><>.dll 文件必须位于以下路径中。 可以修改并添加路径,也可以将文件复制到已建立的路径中。

  • 64 位 DLL

    %Path%;C:\sqljdbc_12.4.1.0_enu\sqljdbc_12.4\enu\auth\x64\mssql-jdbc_auth-12.4.1.x64.dll

  • 32 位 DLL

    %Path%;C:\sqljdbc_12.4.1.0_enu\sqljdbc_12.4\enu\auth\x86\mssql-jdbc_auth-12.4.1.x86.dll

还必须创建 Jaas.conf 文件。 默认情况下,此文件不附带驱动程序,也不会随 Java 一起安装。 若要帮助环境找到此文件,请使用以下方法之一:

注意

Jaas.conf 文件将允许 Java 使用已登录用户的当前上下文。 它还会告知 Java 使用当前缓存的 Kerberos 票证。

  • 修改 Java.Security 文件中的以下行:

    # Default login configuration file
    
    login.config.url.1=C:=\<Path to the File>\jaas.conf
    
  • 或者,在加载环境或应用程序时,通过参数添加 Jaas.conf 文件。 编译 Java 文件时,请确保使用相同的参数:

    javac -Djava.security.auth.login.config=c:\myDirectory\Jaas.conf myapp.java
    java -Djava.security.auth.login.config=c:\myDirectory\Jaas.conf myapp
    

若要使用 Kerberos 集成身份验证与 SQL Server 建立连接,请配置 Jaas.conf 文件:

SQLJDBCDriver {
com.sun.security.auth.module.Krb5LoginModule required 
useTicketCache=true; 
};

连接字符串为 String connectionUrl = "jdbc:sqlserver://<ServerName>:<PortNum>;integratedSecurity=true;Domain=<MyyDomain>;trustServerCertificate=true;javaAuthentication=JavaKerberos;"

代码示例

所有 JDBC 驱动程序都附带了 \sqljdbc_12.4\enu\samples 目录中的示例代码。 最常用的一个是 \sqljdbc_12.4\enu\samples\connections\ConnectURR.java。 创建名为 ConnectURL.java的文件,或使用 驱动程序提供的示例中的ConnectURL.java

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class ConnectURL {
    public static void main(String[] args) {

        // Create a variable for the connection string. Base the connection string on the previous examples supplied in the above documentation.
        String connectionUrl = "jdbc:sqlserver://ServerName:Port;user=SQLAuthAccount;password=SomePassword;trustServerCertificate=true;";

        try (Connection con = DriverManager.getConnection(connectionUrl); Statement stmt = con.createStatement();) 
	{
                String SQL = "SELECT @@version";
	        ResultSet rs = stmt.executeQuery(SQL);
                // Iterate through the data in the result set and display it.
                while (rs.next()) 
		{
                     System.out.println(rs.getString(1));
            	}
        }
        // Handle any errors that may have occurred.
        catch (SQLException e) 
        {e.printStackTrace();    }
  }
}

JDBC 驱动程序跟踪

通常,我们始终希望将跟踪设置为 FINEST 更多详细信息。 驱动程序跟踪有两种方法: 以编程方式 启用跟踪,并使用 logging.properties 文件启用跟踪。

如果选择使用 logging.properties 文件,则必须找到 logging.properties 文件的正确环境$JAVA_HOME\conf\$JAVA_HOME\jre\lib 是两个可能的位置。

按照以下步骤配置此文件:

  1. 修改 logging.properties 文件,以确保它类似于以下全局属性:

    ############################################################
    #  Global properties
    ############################################################
    # "handlers" specifies a comma-separated list of log Handler
    # classes. These handlers will be installed during VM startup.
    # Note that these classes must be on the system classpath.
    # By default, we only configure a ConsoleHandler, which will only
    # show messages at the INFO and above levels.
    
    handlers= java.util.logging.ConsoleHandler
    
    # To also add the FileHandler, use the following line instead.
    #handlers= java.util.logging.FileHandler
    
    # Default global logging level.
    # This specifies which kinds of events are logged across
    # all loggers.  For any given facility this global level
    # can be overridden by a facility-specific level
    # Note that the ConsoleHandler also has a separate level
    # setting to limit messages printed to the console.
    
    .level= INFO
    

    处理程序告知 Java 导出输出的位置。 FileHandler 写入文件的位置有两个,ConsoleHandler 将写入控制台窗口。 输出将生成大量数据,因此需要将其写入文件。

    • 批注行

      #handlers= java.util.logging.ConsoleHandler
      
    • 取消注释行

      handlers= java.util.logging.FileHandler
      

    注意

    OFF设置为.level控制台窗口,并且不会在控制台窗口中看到消息。

     .level=OFF
    
  2. 设置特定的 FileHandler 日志记录:

    ############################################################
    # Handler specific properties.
    # Describes specific configuration info for Handlers.
    ############################################################
    
    # default file output is in user's home directory.
    java.util.logging.FileHandler.pattern = %h/java%u.log
    java.util.logging.FileHandler.limit = 50000
    java.util.logging.FileHandler.count = 1
    # Default number of locks FileHandler can obtain synchronously.
    # This specifies maximum number of attempts to obtain lock file by FileHandler
    # implemented by incrementing the unique field %u as per FileHandler API documentation.
    java.util.logging.FileHandler.maxLocks = 100
    java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
    
    # Limit the messages that are printed on the console to INFO and above.
    java.util.logging.ConsoleHandler.level = INFO
    java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
    
    # Example to customize the SimpleFormatter output format
    # to print one-line log message like this:
    #     <level>: <log message> [<date/time>]
    #
    # java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n
    
  3. 修改此部分以确保其类似于或包含以下行:

    java.util.logging.FileHandler.pattern = /Path/java%u.log
    java.util.logging.FileHandler.limit = 5000000
    java.util.logging.FileHandler.count = 20
    java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
    java.util.logging.FileHandler.level = FINEST
    
  4. 修改行 java.util.logging.FileHandler.pattern = %h/java%u.log 并替换为 %h/ 要存储文件的路径。 例如:

    java.util.logging.FileHandler.pattern = c:/Temp/java%u.log

  5. 设置驱动程序日志记录级别:

    在以下部分底部添加 com.microsoft.sqlserver.jdbc.level=FINEST

    ############################################################
    # Facility-specific properties.
    # Provides extra control for each logger.
    ############################################################
    
    # For example, set the com.xyz.foo logger to only log SEVERE
    # messages:
    # com.xyz.foo.level = SEVERE
    
  6. 保存更改。

    该文件应如下所示:

    ############################################################
    #  Default Logging Configuration File
    #
    # You can use a different file by specifying a filename
    # with the java.util.logging.config.file system property.
    # For example, java -Djava.util.logging.config.file=myfile
    ############################################################
    
    ############################################################
    #  Global properties
    ############################################################
    
    # "handlers" specifies a comma-separated list of log Handler
    # classes.  These handlers will be installed during VM startup.
    # Note that these classes must be on the system classpath.
    # By default we only configure a ConsoleHandler, which will only
    # show messages at the INFO and above levels.
    #handlers= java.util.logging.ConsoleHandler
    
    # To also add the FileHandler, use the following line instead.
    handlers= java.util.logging.FileHandler
    
    # Default global logging level.
    # This specifies which kinds of events are logged across
    # all loggers.  For any given facility this global level
    # can be overridden by a facility-specific level
    # Note that the ConsoleHandler also has a separate level
    # setting to limit messages printed to the console.
    .level= OFF
    
    ############################################################
    # Handler specific properties.
    # Describes specific configuration info for Handlers.
    ############################################################
    
    # default file output is in user's home directory.
    java.util.logging.FileHandler.pattern = c:/Temp/java%u.log
    java.util.logging.FileHandler.limit = 50000
    java.util.logging.FileHandler.count = 1
    # Default number of locks FileHandler can obtain synchronously.
    # This specifies maximum number of attempts to obtain lock file by FileHandler
    # implemented by incrementing the unique field %u as per FileHandler API documentation.
    java.util.logging.FileHandler.maxLocks = 100
    java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
    
    # Limit the messages that are printed on the console to INFO and above.
    #java.util.logging.ConsoleHandler.level = INFO
    #java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
    
    # Example to customize the SimpleFormatter output format
    # to print one-line log message like this:
    #     <level>: <log message> [<date/time>]
    #
    # java.util.logging.SimpleFormatter.format=%4$s: %5$s [%1$tc]%n
    
    ############################################################
    # Facility-specific properties.
    # Provides extra control for each logger.
    ############################################################
    
    # For example, set the com.xyz.foo logger to only log SEVERE
    # messages:
    # com.xyz.foo.level = SEVERE
    com.microsoft.sqlserver.jdbc.level=FINEST
    

重现错误后,还原更改以阻止记录器创建文件。

或者,可以创建或复制上述文本,将其保存到文件,并在加载应用程序时将该文件添加到启动命令。

java -Djava.util.logging.config.file=c:\<Path to the file>\logging.properties myapp

这样,就可以识别默认目录中$JAVA_HOME\conf\$JAVA_HOME\jre\lib未通过命令行指定的 logging.properties 文件。

第三方信息免责声明

本文中提到的第三方产品由 Microsoft 以外的其他公司提供。 Microsoft 不对这些产品的性能或可靠性提供任何明示或暗示性担保。