首页 > 解决方案 > 无需事先编译即可执行 sbt 任务(用于使用 JOOQ 生成数据库类)

问题描述

我有一个由 sbt 构建的 PlayFramework 2.7 应用程序。

为了访问数据库,我使用的是 JOOQ。如您所知,JOOQ 读取我的数据库模式并生成 Java 源类,然后在我的应用程序中使用它们。

只有存在数据库类时,应用程序才会编译。

我正在使用这个自定义 sbt 任务生成类:

// https://mvnrepository.com/artifact/org.jooq/jooq-meta
libraryDependencies += "org.jooq" % "jooq-meta" % "3.12.1"

lazy val generateJOOQ = taskKey[Seq[File]]("Generate JooQ classes")
generateJOOQ := {
  (runner in Compile).value.run("org.jooq.codegen.GenerationTool",
  (fullClasspath in Compile).value.files,    
  Array("conf/db.conf.xml"),
  streams.value.log).failed foreach (sys error _.getMessage)
  ((sourceManaged.value / "main/generated") ** "*.java").get
}

我四处搜索并找到了上面的脚本并根据我的需要对其进行了一些修改,但我并不真正理解它,因为 sbt/scala 对我来说是新的。

现在的问题是,当我启动时generateJOOQsbt 尝试先编译项目,但失败了,因为缺少数据库类。所以我要做的是,注释掉所有使用生成的类的代码,执行编译我的项目的任务,生成数据库类,然后再次启用注释掉的代码。这是一种痛苦!

我想问题出在命令上(runner in Compile),但我没有找到任何可能在不先编译的情况下执行我的自定义任务。

请帮忙!谢谢!

标签: sbtplayframework-2.0jooq

解决方案


通常,当你想生成源时,你应该使用源生成器,见https://www.scala-sbt.org/1.x/docs/Howto-Generating-Files.html

sourceGenerators in Compile += generateJOOQ

这样做会自动导致 SBT 在尝试编译 Scala/Java 源代码之前先执行您的任务。

然后,您不应该真正使用 runner 任务,因为它用于运行您的项目,这取决于 compile 任务,当然需要先执行。

您应该将 jooq-meta 库添加为构建的依赖项,而不是您的源代码。这意味着您应该将libraryDependencies += "org.jooq" % "jooq-meta" % "3.12.1"行例如添加到project/jooq.sbt.

然后,您可以像往常一样在任务中简单地调用 jooq 的 GenerationTool:

// build.sbt

generateJOOQ := {
  org.jooq.codegen.GenerationTool.main(Array("conf/db.conf.xml"))
  ((sourceManaged.value / "main/generated") ** "*.java").get
}

推荐阅读