groovy: Caught: java.sql.SQLException:没有找到合适的驱动程序,即使使用@GrabC



我有这个测试代码连接到SQL Server:

@GrabConfig(systemClassLoader=true)
@Grab(group='com.microsoft.sqlserver', module='mssql-jdbc', version='9.2.1.jre8')
import groovy.sql.Sql
def server = '10.6.6.1'
def port = '1433'
def user = 'sa'
def password = 'somepassword'
def url = "jdbc:sqlserver://${server}:${port};databaseName=master;"
Sql.withInstance(url, user, password) { sql ->
def serverName = sql.firstRow('SELECT @@SERVERNAME')
assert serverName[0]
}

如果我运行它,我得到:

catch: java.sql.SQLException: No suitable driver found for jdbc:sqlserver://10.6.6.1:1433;sqlserver://10.6.6.1:1433;databaseName=master;test.run (test.groovy: 12)

驱动程序的jar肯定是由Grape下载的,因为在我的主目录.groovy/目录的子目录中我可以找到它。

但是没有办法我无法连接到服务器。

我正在使用groovy 3.0.9,但我尝试过旧版本,它是一样的。

编辑:

如果我在连接前添加代码:

Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver")

它工作,但它很奇怪,我确信这是不必要的了。如果有人能解释一下。

仍然需要在java.sql.DriverManager中注册sql驱动程序

每个jdbc驱动程序大约包含以下代码,通常在XyzDriver类中:

static {
try {
java.sql.DriverManager.registerDriver( new XyzDriver() )
} catch (SQLException e) {
...
}
}

与microsoft sql driver相同:https://github.com/microsoft/mssql-jdbc/blob/09d35bfc2338f1fc7c41a958d1e627fa0d6a2b65/src/main/java/com/microsoft/sqlserver/jdbc/SQLServerDriver.java#L732

这就是为什么你必须调用Class.forName("XyzDriver")这样的代码来使驱动程序在DriverManager

中自注册

UPD: JDBC 4.0/java8+

from javadoc: https://docs.oracle.com/javase/8/docs/api/java/sql/DriverManager.html

JDBC 4.0驱动程序必须包含文件META-INF/services/java.sql.Driver

当getConnection方法被调用时,DriverManager将尝试从那些在初始化时加载的驱动程序和那些使用与当前applet或应用程序相同的类加载器显式加载的驱动程序中找到合适的驱动程序。

mssql-jdbc-9.2.1.jre8.jar兼容4.0。META-INF/services/java.sql.Driver文件中包含com.microsoft.sqlserver.jdbc.SQLServerDriver

然而,让我们检查一下DriverManager代码以及它如何查找驱动程序:

http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/sql/DriverManager.java l100

static {
loadInitialDrivers();
println("JDBC DriverManager initialized");
}

DriverManager试图在加载时找到驱动程序。因此,JDBC驱动程序必须在应用程序启动时出现在类路径中才能自动注册。

,而代码中的@Grab则不是这样。

作为抓取后的解决方案,你可以这样做,为所有驱动程序调用self-register:

ServiceLoader.load(java.sql.Driver.class).iterator().findAll()

最新更新