用于 Oracle 的 Slick 3.0 自定义代码生成
Slick 3.0 Custom Code Generation for Oracle
我正在尝试为 Oracle 生成 Slick 3.0 代码。数据库用户指向两个具有同名表的模式,因此生成的代码具有重复的 类。我想从以 "STAGE"
结尾的模式中过滤掉表
代码如下:
object CodeGen2 extends App {
//
val slickDriver = "com.typesafe.slick.driver.oracle.OracleDriver"
val jdbcDriver = "oracle.jdbc.OracleDriver"
val url = "jdbc:oracle:thin:@dbhost:1521:dbsid"
val user = "dbuser"
val password = "dbpassword"
val destDir = "src/main/scala"
val destPackage = "com.mycompany.mypackage"
import scala.concurrent.{ExecutionContext, Await, Future}
import scala.concurrent.duration.Duration
import slick.codegen.SourceCodeGenerator
import scala.concurrent.ExecutionContext.Implicits.global
import slick.jdbc.JdbcModelBuilder
import slick.jdbc.meta.MTable
import com.typesafe.slick.driver.oracle.OracleDriver
import slick.jdbc.JdbcBackend.DatabaseFactoryDef
println("Starting codegen...")
val db = OracleDriver.simple.Database.forURL(url, user=user, password=password, driver=jdbcDriver)
val filteredTables = OracleDriver.defaultTables.filter(
(t: MTable) => !t.name.schema.get.endsWith("STAGE")
)
val modelAction = OracleDriver.createModel(filteredTables, true)
println("Generating model...")
val model = Await.result(db.run(modelAction), Duration.Inf)
val codegen = new SourceCodeGenerator(model) {
// for illustration
val noStage = model.tables.filter { table => !table.name.schema.get.endsWith("STAGE") }
noStage.foreach { table => println(table.name.schema.get) }
}
println("Generating files...")
codegen.writeToFile(
slickDriver, destDir, destPackage, "Tables", "Tables.scala"
)
// slick.codegen.SourceCodeGenerator.main(
// Array(slickDriver, jdbcDriver, url, destDir, destPackage, user, password)
// )
println("Finished codegen.")
}
我尝试过滤 defaultTables 但签名是 Seq[MTable] => Boolean 所以我不知道如何处理它。过滤传递给 driver.createModel 的表格是正确的方法吗?我查看并尝试了其他带有 override(n) 方法的代码,但似乎没有任何可行的方法。
name := "slick-test"
version := "1.0"
scalaVersion := "2.11.6"
libraryDependencies ++= Seq(
"com.typesafe.slick" %% "slick" % "3.0.0",
"org.slf4j" % "slf4j-nop" % "1.6.4",
"com.typesafe.slick" %% "slick-extensions" % "3.0.0",
"com.typesafe.slick" %% "slick-codegen" % "3.0.0"
)
resolvers += "Typesafe Releases" at "http://repo.typesafe.com/typesafe/maven-releases/"
谢谢。
这样试试:
val filteredTables = OracleDriver.defaultTables.map(seq => seq.filter(t => !t.name.schema.get.endsWith("STAGE")))
val modelAction = OracleDriver.createModel(Option(filteredTables), true)
更新:我在上面发帖后,发现了 Oracle 代码生成问题的解决方法。它应该在 Slick 3.2 中修复。用这个 SourceCodeGenerator 替换上面的代码。参见 https://github.com/slick/slick/issues/1000
val codegen = new SourceCodeGenerator(model) {
// slated for fix in 3.2
override def Table = new Table(_) { table =>
// override generator responsible for columns
override def Column = new Column(_) {
override def defaultCode = v => {
def raw(v: Any) = rawType match {
case "String" => "\"" + v + "\""
case "Long" => v + "L"
case "Float" => v + "F"
case "Char" => "'" + v + "'"
case "scala.math.BigDecimal" => v.toString.trim + "d"
case "Byte" | "Short" | "Int" | "Double" | "Boolean" => v.toString
}
v match {
case Some(x) => s"Some(${raw(x)})"
case None => "None"
case x => raw(x)
}
}
}
}
}
我正在尝试为 Oracle 生成 Slick 3.0 代码。数据库用户指向两个具有同名表的模式,因此生成的代码具有重复的 类。我想从以 "STAGE"
结尾的模式中过滤掉表代码如下:
object CodeGen2 extends App {
//
val slickDriver = "com.typesafe.slick.driver.oracle.OracleDriver"
val jdbcDriver = "oracle.jdbc.OracleDriver"
val url = "jdbc:oracle:thin:@dbhost:1521:dbsid"
val user = "dbuser"
val password = "dbpassword"
val destDir = "src/main/scala"
val destPackage = "com.mycompany.mypackage"
import scala.concurrent.{ExecutionContext, Await, Future}
import scala.concurrent.duration.Duration
import slick.codegen.SourceCodeGenerator
import scala.concurrent.ExecutionContext.Implicits.global
import slick.jdbc.JdbcModelBuilder
import slick.jdbc.meta.MTable
import com.typesafe.slick.driver.oracle.OracleDriver
import slick.jdbc.JdbcBackend.DatabaseFactoryDef
println("Starting codegen...")
val db = OracleDriver.simple.Database.forURL(url, user=user, password=password, driver=jdbcDriver)
val filteredTables = OracleDriver.defaultTables.filter(
(t: MTable) => !t.name.schema.get.endsWith("STAGE")
)
val modelAction = OracleDriver.createModel(filteredTables, true)
println("Generating model...")
val model = Await.result(db.run(modelAction), Duration.Inf)
val codegen = new SourceCodeGenerator(model) {
// for illustration
val noStage = model.tables.filter { table => !table.name.schema.get.endsWith("STAGE") }
noStage.foreach { table => println(table.name.schema.get) }
}
println("Generating files...")
codegen.writeToFile(
slickDriver, destDir, destPackage, "Tables", "Tables.scala"
)
// slick.codegen.SourceCodeGenerator.main(
// Array(slickDriver, jdbcDriver, url, destDir, destPackage, user, password)
// )
println("Finished codegen.")
}
我尝试过滤 defaultTables 但签名是 Seq[MTable] => Boolean 所以我不知道如何处理它。过滤传递给 driver.createModel 的表格是正确的方法吗?我查看并尝试了其他带有 override(n) 方法的代码,但似乎没有任何可行的方法。
name := "slick-test"
version := "1.0"
scalaVersion := "2.11.6"
libraryDependencies ++= Seq(
"com.typesafe.slick" %% "slick" % "3.0.0",
"org.slf4j" % "slf4j-nop" % "1.6.4",
"com.typesafe.slick" %% "slick-extensions" % "3.0.0",
"com.typesafe.slick" %% "slick-codegen" % "3.0.0"
)
resolvers += "Typesafe Releases" at "http://repo.typesafe.com/typesafe/maven-releases/"
谢谢。
这样试试:
val filteredTables = OracleDriver.defaultTables.map(seq => seq.filter(t => !t.name.schema.get.endsWith("STAGE")))
val modelAction = OracleDriver.createModel(Option(filteredTables), true)
更新:我在上面发帖后,发现了 Oracle 代码生成问题的解决方法。它应该在 Slick 3.2 中修复。用这个 SourceCodeGenerator 替换上面的代码。参见 https://github.com/slick/slick/issues/1000
val codegen = new SourceCodeGenerator(model) {
// slated for fix in 3.2
override def Table = new Table(_) { table =>
// override generator responsible for columns
override def Column = new Column(_) {
override def defaultCode = v => {
def raw(v: Any) = rawType match {
case "String" => "\"" + v + "\""
case "Long" => v + "L"
case "Float" => v + "F"
case "Char" => "'" + v + "'"
case "scala.math.BigDecimal" => v.toString.trim + "d"
case "Byte" | "Short" | "Int" | "Double" | "Boolean" => v.toString
}
v match {
case Some(x) => s"Some(${raw(x)})"
case None => "None"
case x => raw(x)
}
}
}
}
}