我的所有表共享了一些列,所以我想为所有表提供默认列。以下是我到目前为止所尝试的内容。我正在使用Slick 3.0。
// created_at and updated_at are the columns every table share
abstract class BaseTable[T](tag: Tag, tableName: String)
extends Table[T](tag, tableName) {
def currentWhenInserting = new Timestamp((new Date).getTime)
def createdAt = column[Timestamp]("created_at", O.Default(currentWhenInserting))
def updatedAt = column[Timestamp]("updated_at", O.Default(currentWhenInserting))
}
实现这一点的简单方法如下所示。
case class Student(
name: String, age: Int,
created_at: Timestamp, updated_at: Timestamp
)
class Students(tag: Tag) extends BaseTable[Student](tag, "students"){
def name = column[String]("name")
def age = column[Int]("age")
override def * : ProvenShape[Student] =
(name, age, createdAt, updatedAt).shaped <>
(Student.tupled, Student.unapply _)
}
但这不可取。
首先,强制每个表行案例类包含created_at和updated_at 。如果我有更多的字段,从API设计角度来看是完全不可接受的。
其次,明确地在(name,age,createdAt,updatedAt)中写下两个 createdAt,updatedAt 。这不是我对Default row的期望。
我解决这个问题的理想方法如下:
case class Student(name: String, age: Int)
class Students(tag: Tag) extends BaseTable[Student](tag, "students"){
def name = column[String]("name")
def age = column[Int]("age")
override def * : ProvenShape[Student] =
(name, age).shaped <>
(Student.tupled, Student.unapply _)
}
也就是说,在BaseTable或Define BaseCaseClass中编写一些方法,以避免在表定义中显式写入额外的两个字段,如学生和行案例类定义学生。
然而,经过痛苦的挣扎,仍然可以完成它。 任何帮助将不胜感激。
答案 0 :(得分:1)
我使用以下模式:
case class Common(arg0: String, arg1: String)
trait Commons { this: Table[_] =>
def arg0 = column[String]("ARG0", O.Length(123))
def arg1 = column[String]("ARG1", O.Length(123))
def common = (arg0, arg1).<> [Meta, (String, String)](
r => {
val (arg0, arg1) = r
Meta(arg0, arg1)
},
o => Some(o.arg0, o.arg1)
)
}
case class MyRecord(a: String, b: String, common: Common)
class MyRecords(tag: Tag) extends Table[MyRecord](tag, "MY_RECORDS") with Commons {
def a = column[String]("A", O.PrimaryKey, O.Length(123))
def b = column[String]("B", O.Length(123))
def * = (a, b, common) <> (MyRecord.tupled, MyRecord.unapply)
}
它并不完美,但它有助于避免重复而不会难以理解。