Scala 在sbt插件中利用库依赖关系

Scala 在sbt插件中利用库依赖关系,scala,build,sbt,lift,Scala,Build,Sbt,Lift,为了管理数据库迁移(通过),我正在与之合作并尝试开始工作。Slick有一个Flyway sbt插件。按照这些说明,我的项目/plugins.sbt文件中有以下内容: resolvers += "Flyway" at "https://flywaydb.org/repo" addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "2.1.0") addSbtPlugin("com.github.mpeltonen" % "sbt-idea" %

为了管理数据库迁移(通过),我正在与之合作并尝试开始工作。Slick有一个Flyway sbt插件。按照这些说明,我的
项目/plugins.sbt
文件中有以下内容:

resolvers += "Flyway" at "https://flywaydb.org/repo"

addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "2.1.0")
addSbtPlugin("com.github.mpeltonen" % "sbt-idea" % "1.6.0")
addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.6.1")
addSbtPlugin("org.flywaydb" % "flyway-sbt" % "4.0.3")
我还向我的项目根目录添加了一个
flyway.sbt
,但由于我没有使用TypeSafe的应用程序配置,而是使用,它看起来如下所示:

import sbt._
import net.liftweb.util.Props

lazy val flywayDBName = "adb"

//Set up local setting key to load configuration into.
lazy val flywayDbConf = settingKey[(String, String, String)]("Lift config file with Slick settings")

flywayDbConf := {
  (Props.get("db.mysql.url"), Props.get("db.mysql.user"), Props.get("db.mysql.password"))
}

flywayUrl := flywayDbConf.value._1

flywayUser := flywayDbConf.value._2

flywayPassword := flywayDbConf.value._3
当然,这不起作用,因为无法导入
net.liftweb.util.Props
,而我的
build.sbt
包含
net.liftweb.util.*
库依赖项,其中包括
net.liftweb.util.
(我知道这一点是因为我使用它来访问
Boot.scala
以及其他地方的属性),此文件无权访问这些依赖项。从命令行执行
sbt
时:

path/to/project/flyway.sbt:2: error: not found: object net
import net.liftweb.util.Props
       ^
sbt.compiler.EvalException: Type error in expression
(顺便说一句,我的IDE还报告库不可用。)

很明显,我走错了方向。库依赖项在构建时不可用是有道理的,但是上面的参考资料表明应该有某种方法来实现相同的效果。我错过了什么?如何缩小属性文件访问和构建脚本之间的差距


请注意,我正试图这样做,以便我可以使用FlywayDb管理项目中的数据库更改,因为我知道底层数据库可能是开发(MySQL)、生产(MySQL或PostGres)或测试(h2)数据库。我希望代码与这些细节无关,但都在同一页上。

其他人可能会回复关于编写sbt插件等的部分,但我们在生产中所做的工作以及至少3年来的良好工作是将db迁移代码全部放在实际的应用程序中,而不是委托给手动运行的sbt任务

虽然我没有写(都归功于蒂姆·尼尔森),但iirc的一部分包括马特·法默在这个项目上所做的

(他开源真是太好了)

我们的工作方式是:

  • scala我们在迁移对象doMigrations()上调用一个方法
  • doMigrations()获取运行数据库的最新版本(我们有一个表(从技术上讲,我们使用Mongo,所以它是一个集合,但MySQl也是如此,从这里开始我们称它为表))在这个表中,每次运行迁移时,我们都会添加一行,其中包含迁移的描述,然后是一个数字id,这是顺序的,从1点开始
  • 然后,我们将其与应用程序中硬编码的最新迁移号进行比较,我们在另一个名为MigrationVersion的对象上有此代码,一个名为“latest”的val 然后我们做一些类似的事情:

    (versionStoredOnDatabase+1 to latestVersionFromMigrationVersion).foreach { ver =>
      ver is the version so here we use reflection to find the migration 
      classes, run the,. save the migration id and description to the
      database so we don't run the migration twice, etc. I think this 
      is where you will want to call flydb
    }
    
  • 因此,这将运行我们拥有的每个迁移,以便数据库迁移版本与我们添加到应用程序的最后一个版本相匹配

    一旦迁移完成,引导将继续正常初始化,然后我们的应用程序将再次运行。不需要sbt,而且它在我们的登台、试点和生产服务器上以开发模式在本地运行良好

    在我们的例子中,我们有几个web服务器,所以我们在一个专用服务器上运行迁移,然后web服务器上的其他应用程序继续运行,但我想你明白了,如果你需要关于这种处理迁移方法的更多信息,请在这里告诉我们

    谢谢


    迭戈

    这是一个局部解决方案:我还没有找到一个完整的解决方案,原因只涉及到这个问题

    有几个重要的概念在文档中没有完全阐明:

    • 在项目的根目录中,应该有
      build.sbt
      文件。在这个根目录中还有一个
      项目
      目录。将
      build.sbt
      文件放在该目录中就是元构建的构建定义。(与正确构建相反,)对此进行了描述
    • 如果适当的构建的构建定义具有库依赖关系(这是我在没有相关词语的情况下试图获得的),那么元构建需要导入库
    • 如果元构建具有库依赖关系,则它可供适当的构建使用。同样,如果深入一层,元构建定义可以导入库供元构建定义使用
    • 如果在元构建中设置了
      scalaVersion
      ,则正确的构建定义将无法正常工作。我不完全清楚为什么,但至少它对应该下载哪些库感到困惑。其中一些原因与SBT 0.13.x被固定到Scala 2.10这一事实有关,因此
      scalaversation
      中定义的任何其他版本的Scala都会引起问题
    • 同样,如果您下载的库是针对不是2.10的Scala版本构建的,则会出现问题
    我只有有限的时间来探索这个问题,并为我的整个问题确定完整的解决方案,所以我的理解仍然是模糊的。但是,这是导入库的方式

    项目/build.sbt
    中:

    // Example library
    libraryDependencies += "net.liftweb" % "lift-webkit_2.10" % "2.6"
    
    import net.liftweb.util.Props
    
    val urlProperty = Props.get("db.mysql.url")
    
    build.sbt
    中:

    // Example library
    libraryDependencies += "net.liftweb" % "lift-webkit_2.10" % "2.6"
    
    import net.liftweb.util.Props
    
    val urlProperty = Props.get("db.mysql.url")
    

    当我一起得到一个更完整的解决方案时,我会更新它。

    有趣<代码>Flywaydb的功能大致相同,但显然是应用程序本身的外部功能。我希望避免编写/重写该功能,而只是使用flyway(或叉车),但这可能是不可避免的。。。特别感谢你的链接!我会调查一下,看看这条路是否更合理。谢谢你的帮助,迭戈!热爱你在社区中所做的工作!