预测试 SBT 任务:无法实例化 JDBC 驱动程序
Posted
技术标签:
【中文标题】预测试 SBT 任务:无法实例化 JDBC 驱动程序【英文标题】:Pre-test SBT task: Unable to instantiate JDBC driver 【发布时间】:2021-06-05 07:00:44 【问题描述】:我在获取 SBT 任务 以使用 Flyway 运行迁移时遇到问题;运行任务时出现异常。有什么想法可以解决吗?
org.flywaydb.core.api.FlywayException: Unable to instance JDBC driver: org.postgresql.Driver => 检查jar文件是否存在
以下代码在我的 测试 (ScalaTest) 中运行 BeforeAll
时有效,但当我将其移至 SBT 任务时无效。
val flyway = Flyway
.configure()
.locations("filesystem:./**/resources/db/migrations/")
.dataSource("jdbc:postgresql://localhost:5432/my_database", "my_user", "secret")
.load()
flyway.clean()
flyway.migrate()
我的/build.sbt
文件如下所示:
import org.flywaydb.core.Flyway
lazy val migrate = taskKey[Unit]("Migrate database")
lazy val migrateTask = Def.task
println("Migrate")
val flyway = Flyway
.configure()
.locations("filesystem:./**/resources/db/migrations/")
.dataSource("jdbc:postgresql://localhost:5432/my_database", "my_user", "secret")
.load()
flyway.clean()
flyway.migrate()
val IntegrationTest = config("integration") extend Test
lazy val integrationTestSettings = inConfig(IntegrationTest)(Defaults.testSettings) ++ List(
IntegrationTest / fork := false,
IntegrationTest / parallelExecution := false,
IntegrationTest / sourceDirectory := baseDirectory.value / "src/test/integration",
IntegrationTest / test :=
(IntegrationTest / test) dependsOn migrateTask
.value
)
lazy val root = Project(id = "hello", base = file("."))
.configs(Configs.all: _*)
.settings(
integrationTestSettings,
libraryDependencies += "org.scalatest" %% "scalatest" % "3.1.4",
)
而我的/project/build.sbt
看起来像这样:
libraryDependencies ++= List(
"org.flywaydb" % "flyway-core" % "7.6.0",
"org.postgresql" % "postgresql" % "42.2.19",
)
我使用的版本是:
SBT:1.4.5 斯卡拉:2.13.4 飞行路线:7.6.0有没有人知道我为什么会收到这个错误,以及如何解决它?
任何帮助将不胜感激。谢谢:)
【问题讨论】:
【参考方案1】:在 Flyway 存储库上搜索,错误消息来自这里 - https://github.com/flyway/flyway/blob/9033185ab8bfa56b0dae9136c04763cdccc50081/flyway-core/src/main/java/org/flywaydb/core/internal/jdbc/DriverDataSource.java#L165-L182 它正在尝试从类加载器加载数据库驱动程序。这些 ClassLoader 技术有时会与 sbt 设置分层 ClassLoader 以运行 sbt 本身发生冲突。这是我对正在发生的事情的猜测。
我们如何解决这个问题?
你说运行它作为测试的一部分是有效的,所以也许你可以为此创建一个子项目?
ThisBuild / scalaVersion := "2.13.4"
lazy val migrate = taskKey[Unit]("Migrate database")
lazy val root = (project in file("."))
.settings(
name := "hello",
migrate := (migrateProj / run).toTask("").value
)
// utility project to run database migration
lazy val migrateProj = (project in file("migrate"))
.settings(
libraryDependencies ++= List(
"org.flywaydb" % "flyway-core" % "7.6.0",
"org.postgresql" % "postgresql" % "42.2.19",
),
Compile / run / fork := true,
publish / skip := true,
)
迁移/Migrate.scala
object Migrate extends App
println("migrate")
// rest of the code here...
现在你可以运行了
sbt:flyway> migrate
[info] running (fork) Migrate
[info] migrate
[success] Total time: 4 s, completed Mar 6, 2021 9:03:07 PM
关于分层类加载器的详细信息
ClassLoader 技术有时会与 sbt 设置分层的 ClassLoader 以运行 sbt 本身发生冲突。 sbt
-the-Bash-script 允许用户使用 project/build.properties
选择 sbt 版本,使用 build.sbt
选择 Scala 版本。这两者都使 sbt build 具有声明性和可重复性,通常是一件好事。但是使用 Scala 2.10 编写的 sbt 启动器如何启动使用 Scala 2.12 编写的 sbt 1.4.x,然后启动您的 Scala 2.13 应用程序?这些边界交叉中的每一个都是通过创建一个分层的 ClassLoader 来完成的,就像电影 Inception 一样。
【讨论】:
以上是关于预测试 SBT 任务:无法实例化 JDBC 驱动程序的主要内容,如果未能解决你的问题,请参考以下文章
如何在 SBT Scala 项目中使用 MySQL JDBC 驱动程序?
[XXX] 注册了JDBC驱动程 序 [oracle.jdbc.OracleDriver]