使用 Slick 创建单列 table

Creating a single column table with Slick

我很习惯像这样编写标准的光滑样板代码。

假设我正在创建一个名为 Foo 的 table,其中包含列 ID 和名称。我们可以写

case class Foo(id: Long, name: String)
final class FooTable(tag: Tag) extends Table[Foo](tag, "foo") {
   def id = column[Long]("id")
   def name = column[String]("name")
   def * = (id, name) <> (Foo.tupled, Foo.unapply)
}

但是如果我想要一个单独的列 table,其中 Foo 只有一个名称怎么办?下面的代码无法编译,因为 Now Foo 不再有元组方法。

case class Foo(name: String)
final class FooTable(tag: Tag) extends Table[Foo](tag, "foo") {
   def name = column[String]("name")
   def * = (name) <> (Foo.tupled, Foo.unapply)
}

我在 SO

上找到了这个帖子

Scala projections in Slick for only one column

并将我的代码更改为

case class Foo(name: String)
final class FooTable(tag: Tag) extends Table[Foo](tag, "foo") {
   def name = column[String]("email_address")
   def * = (name)
}

但仍然无法编译

在单个参数的情况下使用Foo.apply _。你的代码变成如下

case class Foo(name: String)

final class FooTable(tag: Tag) extends Table[Foo](tag, "foo") {
  def name = column[String]("name")
  def * = (name) <> ((Foo.apply _), Foo.unapply)
}

解释:

scala> case class Foo(name: String)
defined class Foo

scala> Foo.apply _
res0: String => Foo = <function1>

在单参数情况下 class Foo.apply _ returns 需要一个函数 1。

但是如果参数不止一个,这是不可能的,所以需要 .tupled

也找到了另一个答案

case class Foo(name: String)
final class FooTable(tag: Tag) extends Table[Foo](tag, "foo") {
   def name = column[String]("name")
   def * = name <> (Foo, Foo.unapply)
}

我相信以前的答案已经解决了这个特定问题。不过,我认为这里有一件事值得补充。

Slick 中没有任何内容需要您将 case classes 用作 unpacked typeunpacked type 是您的模型,在这种情况 Foo).

在您的投影中:

def * = (id, name) <> (Foo.tupled, Foo.unapply)

你可以传递任何你想要的两个函数,假设:

  • 第一个将从元组(投影中的 2+ 列)或值(1 列投影)

  • 中创建您的 unpacked type
  • second 将创建元组(同样是在投影中有 2+ 列的情况下)或
    值(1 列投影)。

只有 case classes 具有开箱即用的方法才方便 (tupled, apply, unapply)。

我希望这可以澄清,即使您缺少此类方法,也总是有可能(在最坏的情况下)例如创建满足给定要求的函数。