Slick 中的自定义列(对象)类型
Custom column (Object) type in Slick
我似乎无法在任何地方找到如何在 Slick 中正确使用自定义列类型,我已经苦苦挣扎了一段时间。光滑 documentation
建议 MappedColumnType
但我发现它仅适用于简单的用例,如原始类型包装器(或者可能只是我不知道如何正确使用它)。
假设我的数据库中有工作table JobsTableDef
class。在 table 中,我有 companyId
和 responsibleUserId
列,它们是 Company
和 User
对象在各自 table 中的外键(CompaniesTableDef
, UsersTableDef
).
class JobsTableDef(tag: Tag) extends Table[Job] (tag, "jobs") {
def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
def title = column[String]("title")
def companyId = column[Long]("companyId")
def responsibleUserId = column[Long]("responsibleUserId")
def companyFK = foreignKey("COMPANY_ID_FK", companyId, companies)(i => i.id)
def responsibleUserFK = foreignKey("RESPONSIBLE_USER_FK", responsibleUserId, users)(i => i.id)
val companies = TableQuery[CompaniesTableDef]
val users = TableQuery[UsersTableDef]
override def * = (id, title, companyId, responsibleUserId) <> (Job.tupled, Job.unapply)
}
class CompaniesTableDef(tag: Tag) extends Table[Company] (tag, "companies") {
def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
def name = column[String]("name")
def about = column[String]("about")
override def * = (id, name, about) <> (Company.tupled, Company.unapply)
}
class UsersTableDef(tag: Tag) extends Table[User] (tag, "users"){
def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
def username = column[String]("username", O.Unique)
override def * = (id, username) <> (User.tupled, User.unapply)
}
我想实现的是自动'deserialize' Company
和User
由他们在Jobs
table 中的ID 表示。例如:
class JobsTableDef(tag: Tag) extends Table[Job] (tag, "jobs") {
def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
def title = column[String]("title")
def company = column[Company]("companyId")
def responsibleUser = column[User]("responsibleUserId")
def companyFK = foreignKey("COMPANY_ID_FK", companyId, companies)(i => i.id.?)
def responsibleUserFK = foreignKey("RESPONSIBLE_USER_FK", responsibleUserId, users)(i => i.id.?)
val companies = TableQuery[CompaniesTableDef]
val users = TableQuery[UsersTableDef]
override def * = (id, title, company, responsibleUser) <> (Job.tupled, Job.unapply)
}
鉴于我的 Job
class 是这样定义的:
case class Job(
id: Long,
title: String,
company: Company,
responsibleUser: User,
)
目前,我正在以老式的方式从数据库中获取 Job
,读取 companyId
和 responsibleUserId
,然后再次查询数据库并手动构建另一个Job
对象(当然我也可以加入tables,获取数据为tuple
,然后构造Job
对象)。我严重怀疑这是要走的路。有没有一种更聪明、更优雅的方法来指示 Slick 自动从另一个 tables 中获取链接对象?
编辑:我正在使用 Play 2.6.12 和 Slick 3.2.2
经过几天的深入调查,我得出的结论是目前在 Slick 中这是不可能的。我正在寻找的可以描述为通过自定义列类型描述的自动连接表。 Slick 确实支持自定义列类型(通过 MappedColumnType
体现,如 docs 中所述),但它仅适用于相对简单的类型,这些类型不是由从 DB 反序列化的另一个对象组成的(至少自动地,你可以总是尝试从数据库中获取另一个对象,然后 Await.result()
结果 Future
对象,但我想这不是一个好的做法)。
所以,回答我自己,'auto joining' 在 Slick 中是不可能的,回到手动对象构建的手动连接。
我似乎无法在任何地方找到如何在 Slick 中正确使用自定义列类型,我已经苦苦挣扎了一段时间。光滑 documentation
建议 MappedColumnType
但我发现它仅适用于简单的用例,如原始类型包装器(或者可能只是我不知道如何正确使用它)。
假设我的数据库中有工作table JobsTableDef
class。在 table 中,我有 companyId
和 responsibleUserId
列,它们是 Company
和 User
对象在各自 table 中的外键(CompaniesTableDef
, UsersTableDef
).
class JobsTableDef(tag: Tag) extends Table[Job] (tag, "jobs") {
def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
def title = column[String]("title")
def companyId = column[Long]("companyId")
def responsibleUserId = column[Long]("responsibleUserId")
def companyFK = foreignKey("COMPANY_ID_FK", companyId, companies)(i => i.id)
def responsibleUserFK = foreignKey("RESPONSIBLE_USER_FK", responsibleUserId, users)(i => i.id)
val companies = TableQuery[CompaniesTableDef]
val users = TableQuery[UsersTableDef]
override def * = (id, title, companyId, responsibleUserId) <> (Job.tupled, Job.unapply)
}
class CompaniesTableDef(tag: Tag) extends Table[Company] (tag, "companies") {
def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
def name = column[String]("name")
def about = column[String]("about")
override def * = (id, name, about) <> (Company.tupled, Company.unapply)
}
class UsersTableDef(tag: Tag) extends Table[User] (tag, "users"){
def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
def username = column[String]("username", O.Unique)
override def * = (id, username) <> (User.tupled, User.unapply)
}
我想实现的是自动'deserialize' Company
和User
由他们在Jobs
table 中的ID 表示。例如:
class JobsTableDef(tag: Tag) extends Table[Job] (tag, "jobs") {
def id = column[Long]("id", O.AutoInc, O.PrimaryKey)
def title = column[String]("title")
def company = column[Company]("companyId")
def responsibleUser = column[User]("responsibleUserId")
def companyFK = foreignKey("COMPANY_ID_FK", companyId, companies)(i => i.id.?)
def responsibleUserFK = foreignKey("RESPONSIBLE_USER_FK", responsibleUserId, users)(i => i.id.?)
val companies = TableQuery[CompaniesTableDef]
val users = TableQuery[UsersTableDef]
override def * = (id, title, company, responsibleUser) <> (Job.tupled, Job.unapply)
}
鉴于我的 Job
class 是这样定义的:
case class Job(
id: Long,
title: String,
company: Company,
responsibleUser: User,
)
目前,我正在以老式的方式从数据库中获取 Job
,读取 companyId
和 responsibleUserId
,然后再次查询数据库并手动构建另一个Job
对象(当然我也可以加入tables,获取数据为tuple
,然后构造Job
对象)。我严重怀疑这是要走的路。有没有一种更聪明、更优雅的方法来指示 Slick 自动从另一个 tables 中获取链接对象?
编辑:我正在使用 Play 2.6.12 和 Slick 3.2.2
经过几天的深入调查,我得出的结论是目前在 Slick 中这是不可能的。我正在寻找的可以描述为通过自定义列类型描述的自动连接表。 Slick 确实支持自定义列类型(通过 MappedColumnType
体现,如 docs 中所述),但它仅适用于相对简单的类型,这些类型不是由从 DB 反序列化的另一个对象组成的(至少自动地,你可以总是尝试从数据库中获取另一个对象,然后 Await.result()
结果 Future
对象,但我想这不是一个好的做法)。
所以,回答我自己,'auto joining' 在 Slick 中是不可能的,回到手动对象构建的手动连接。