表中的slick documentation列中定义了def
class Coffees(tag: Tag) extends Table[(String, Int, Double, Int, Int)](tag, "COFFEES") {
def name = column[String]("COF_NAME", O.PrimaryKey)
def supID = column[Int]("SUP_ID")
def price = column[Double]("PRICE")
def sales = column[Int]("SALES", O.Default(0))
def total = column[Int]("TOTAL", O.Default(0))
def * = (name, supID, price, sales, total)
}
有没有理由不应该这样:
class Coffees(tag: Tag) extends Table[(String, Int, Double, Int, Int)](tag, "COFFEES") {
val name = column[String]("COF_NAME", O.PrimaryKey)
val supID = column[Int]("SUP_ID")
val price = column[Double]("PRICE")
val sales = column[Int]("SALES", O.Default(0))
val total = column[Int]("TOTAL", O.Default(0))
val * = (name, supID, price, sales, total)
}
似乎列不会使用任何可能发生变化的内容。
答案 0 :(得分:3)
简短回答: 初始化顺序。
答案很长:
让我们收集一些事实:
1)使用val
代替def
s主要有效(如果您在代码中将大部分def
更改为val
s,那么大部分时间行为正确 - 至少这是我的工作方式)
2)Slick
代码的大多数示例都使用def
s。
因此,如果出现错误,可能只会发生在某些(罕见?)案件中。
Slick
本身的代码中可能会有一些亮点(看看if(tt == null)
之后的注释(类`RelationalProfile):
def column[C](n: String, options: ColumnOption[C]*)(implicit tt: TypedType[C]): Rep[C] = {
if(tt == null) throw new NullPointerException(
"implicit TypedType[C] for column[C] is null. "+
"This may be an initialization order problem. "+
"When using a MappedColumnType, you may want to change it from a val to a lazy val or def.")
new Rep.TypedRep[C] {
override def toNode =
Select((tableTag match {
case r: RefTag => r.path
case _ => tableNode
}), FieldSymbol(n)(options, tt)) :@ tt
override def toString = (tableTag match {
case r: RefTag => "(" + _tableName + " " + r.path + ")"
case _ => _tableName
}) + "." + n
}
}
如果您查看引入此更改的提交:https://github.com/slick/slick/commit/be2ff6513d46abc9a25c8752c2931a786d4c5ad6
你应该找到很好的解释(提交评论)。