尝试使用表格填充数据库时遇到问题(使用Slick 2.0.0):
import scala.slick.driver.JdbcDriver
import scala.slick.lifted.TableQuery
case class DemoInit(slickDriver:JdbcDriver, tables:Seq[TableQuery[_]]) {
lazy val db = slickDriver.simple.Database.forURL("jdbc_url", "user", "pass", driver = "com.example.Driver")
import slickDriver.simple.{tableQueryToTableQueryExtensionMethods, ddlToDDLInvoker}
def init() {
db withSession { implicit session =>
tables.map(_.ddl).reduce(_ ++ _).create
}
}
}
尝试编译上面的代码会导致以下两个错误:
value ddl is not a member of scala.slick.lifted.TableQuery[_$1]
value create is not a member of scala.slick.lifted.TableQuery[_$1]
我猜测类型参数没有被正确推断。我做错了什么?
答案 0 :(得分:3)
您需要为表类型添加正确的约束:
tables: Seq[TableQuery[_ <: Table[_]]]
在没有采用您期望的隐式转换的情况下,添加对此转换的显式调用会有所帮助。这将为您提供更好的错误消息,解释转换不适用的原因。
然后您将遇到您使用reduce
错误的下一个问题。您可能希望使用类似tables.map(_.ddl).reduce(_ ++ _)
的内容。
由于Table
与路径有关,因此您无法将其用于尝试将所有内容作为参数传递给类的设置。虽然允许您在def
的后续参数列表中引用先前参数列表中的路径相关类型,但这在class
中是不可能的。您必须以不同方式构造代码以使路径依赖类型正确,例如:
import scala.slick.driver.JdbcProfile
class DemoDAO(val slickDriver: JdbcProfile) {
import slickDriver.simple._
lazy val db = slickDriver.simple.Database.forURL("jdbc_url", "user", "pass", driver = "com.example.Driver")
def init(tables: Seq[TableQuery[_ <: Table[_]]]) {
db withSession { implicit session =>
tables.map(_.ddl).reduce(_ ++ _).create
}
}
}
}
答案 1 :(得分:2)
我最终做的是创造一个新的特性:
import scala.slick.driver.JdbcProfile
trait TablesSupplier {
def tables(profile:JdbcProfile):Seq[JdbcProfile#SimpleQL#TableQuery[_ <: JdbcProfile#SimpleQL#Table[_]]]
}
我正在使用Slick生成表对象的源代码,因此我有一个Tables
特征,我在TablesSupplier
的实现中使用它:
import scala.slick.driver.JdbcProfile
object DemoTablesSupplier extends TablesSupplier {
def tables(profile:JdbcProfile) = {
val _profile = profile
val demoTables = new Tables { val profile = _profile }
import demoTables._
Seq(Table1, Table2, Table3)
}
}
所以,我的DemoInit
现在看起来像这样:
import scala.slick.driver.JdbcDriver
case class DemoInit(slickDriver:JdbcDriver, tables:Seq[TableQuery[_]]) {
lazy val db = slickDriver.simple.Database.forURL("jdbc_url", "user", "pass", driver = "com.example.Driver")
import slickDriver.simple.{tableQueryToTableQueryExtensionMethods, ddlToDDLInvoker}
def init() {
db withSession { implicit session =>
val profile = slickDriver.profile
//import the type of Table and TableQuery that are expected as well as two implicit methods that are necessary in order to use 'ddl' and 'create' methods
import profile.simple.{Table, TableQuery, tableQueryToTableQueryExtensionMethods, ddlToDDLInvoker}
//using asInstanceOf is very ugly but I couldn't figure out a better way
val tables = tablesCreator.tables(profile).asInstanceOf[Seq[TableQuery[_ <: Table[_]]]]
tables.map(_.ddl).reduce(_ ++ _).create
}
}
}