gpt4 book ai didi

jdbc - DriverManager 在 gradle 自定义插件的任务中看不到依赖项

转载 作者:行者123 更新时间:2023-12-03 05:37:11 26 4
gpt4 key购买 nike

我正在编写一些 gradle 插件,现在我遇到了 DriverManager 没有看到 buildscript 依赖项中定义的 JDBC 驱动程序的问题:

我有下一个 build.gradle 文件:

buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("com.h2database:h2:1.4.196")
}
}
plugins {
id "someplugin"
}
apply plugin: 'groovy'

当我调用在扩展 DefaultTask 的任务中定义的命令时
DriverManager.getConnection("jdbc:h2:mem:", "sa", "")

我收到异常
No suitable driver found for jdbc:h2:mem:

当我对这些类进行单元测试时没有问题 - 只有当我调用调用 DriverManager.getConnection 的插件任务时才会发生这种情况。

我在这里想念什么?谢谢!

最佳答案

好吧,有一个关于为什么 DriverManager 的答案。不像您使用它以及如何使其工作那样工作,并且有一个关于如何正确使用 Groovy 中的 SQL(这是 Gradle 脚本的基础)的答案。我将从使用 Groovy 中的 SQL 的正确方法开始:

从 Gradle/Groovy 正确使用 SQL:

不幸的是要使用 Groovy Sql 类,将驱动添加到 buildscript 类路径是不够的,您需要将驱动添加到正确的类加载器中,否则将无法正常工作。

除了将驱动程序添加到 JVM 的 ext 目录之外,您还可以像这样动态地执行此操作:

configurations { jdbc }
jdbc 'com.h2database:h2:1.4.196'
def sqlClassLoader = Sql.classLoader
configurations.jdbc.each { sqlClassLoader.addURL it.toURI().toURL() }
Sql.withInstance('jdbc:h2:mem:', 'sa', '', 'org.h2.Driver') {
it.execute 'your sql here'
}

正确使用DriverManager :

您不能使用 DriverManager由于 Groovy 的动态性,就像您所做的那样。在您使用的方法中, DriverManager尝试从调用堆栈中动态找到调用者类,然后使用该类的类加载器来查找数据库驱动程序。使用 Groovy,这是找到的一些动态代理类,因此在其类加载器中找不到数据库驱动程序。

如果您改为提供 DriverManager正确的调用者类,如 DriverManager.getConnection("jdbc:h2:mem:", [user: "sa", password: ""] as Properties, getClass()) ,它工作正常。或者,也可以不提供任何调用者类,如 DriverManager.getConnection("jdbc:h2:mem:", [user: "sa", password: ""] as Properties, null)在这种情况下,使用当前线程上下文类加载器,这也很好。

Gradle 中的自动驱动程序查找问题:

当类 DriverManager已加载,它会扫描系统属性 jdbc.drivers以及提供 java.sql.Driver 的所有服务服务。它遍历那些找到的类并实例化它们。驱动程序本身通常会响应向 DriverManager 注册自己。他们现在可以这样做,以便稍后像我上面建议的那样进行自动查找。

现在的问题是,如果您正在使用 Gradle 守护程序(这是现在的默认设置),并在该守护程序中运行任何构建来加载 DriverManager (例如,在您以前的尝试中),那么该类已经加载。如果您稍后将 buildscript 依赖项添加到 H2(或在它不存在但 DriverManager 已加载的版本之后运行它存在的构建),则该类已加载并且不会查找现在位于的驱动程序类路径。

这里有一些可能的解决方法,没有明确命名驱动程序类,从可能最坏到可能最好的解决方案:
  • 为您的构建禁用守护程序,并确保没有人使用您的构建启用该守护程序。这很难控制和执行,并且会降低构建性能。
  • 使用私有(private)方法DriverManager.loadInitialDrivers()在调用 getConnection 之前确保再次完成查找并自动添加 H2 驱动程序。更好,但使用私有(private)方法。
  • 使用 ServiceLoader自己加载所有Driver类路径中的类,以使它们向 DriverManager 进行自我注册喜欢 ServiceLoader.load(Driver.class).collect()getConnection 之前称呼。可能是最优雅的解决方案。

  • 这里有一些明确命名驱动程序类的可能解决方法:
  • 在使用 getConnection() 之前只需加载类使其通过 org.h2.Driver.toString() 自行注册
  • 在使用 getConnection() 之前只需加载类使其通过 Class.forName 'org.h2.Driver' 自行注册
  • 关于jdbc - DriverManager 在 gradle 自定义插件的任务中看不到依赖项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55262588/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com