将类映射为类中的列类型

时间:2014-07-20 21:49:58

标签: scala slick slick-2.0

我理解在使用Long, Int, String等类型时如何做到这一点。但是说我有一个类在其他类中有字段,如下所示:

case class Foo(a:String, b:String)
case class Bar(foo:Option[Foo], c:String)

如何为自定义类型(Foo类中的Bar)设置映射器?

class Bars(tag:Tag) extends Table[Bar](tag, "BARS") {
  def foo = column[Foo]("FOO") // <- won't work
  def c = column[String]("C")

  def * = (foo, c) <> (Bar.tupled, Bar.unapply)
}

documentation链接)


更新

数据库驱动程序:slick.driver.PostgresDriver

Slick 2

我猜测原始SQL看起来像这样:

"BARS" (
  "A" VARCHAR(254) NOT NULL,
  "B" VARCHAR(254) NOT NULL, 
  "C" VARCHAR(254) NOT NULL
);

应该可以这样调用Bar

val bar = Bar(Foo("1", "2"), "3")
barTable.insert(bar)
bar.foo.a // 1
bar.foo.b // 2
bar.c // 3

2 个答案:

答案 0 :(得分:1)

您可以在案例类和可以存储在数据库中的某种类型之间编写映射器。

请参阅Slick的示例:http://slick.typesafe.com/doc/1.0.0/lifted-embedding.html,位于页面末尾。

在您的情况下,一种简单的方法可能是将您的案例类转换为json并存储为字符串。 (如果你的数据库直接支持json类型,比如PostgreSQL,你可以在列映射器中指定JSON类型,这样可以在进行与案例类内容相关的查询时获得优势。)

import org.json4s._
import org.json4s.native.Serialization
import org.json4s.native.Serialization.{read, write}

//place this in scope of your table definition
implicit val FooTypeMapper = MappedTypeMapper.base[Foo, String](
  { f => write(f) },    // map Foo to String
  { s => read[Too](s) } // map String to Foo
)

class Bars(tag:Tag) extends Table[Bar](tag, "BARS") {
  def foo = column[Foo]("FOO") // <- should work now
  def c = column[String]("C")

  def * = (foo, c) <> (Bar.tupled, Bar.unapply)
}

使用PostgreSQL&gt; = 9.3,你也可以写:

def foo = column[Foo]("FOO", O.DBType("json"))

这样DB就能正确对待你的json。

更新:如果为JSON字段发送字符串,则应设置连接属性。像这样:

  val prop = new java.util.Properties
  prop.setProperty("stringtype", "unspecified")

  val db = Database.forURL(<db-uri>,
                           driver="org.postgresql.Driver",
                           user=<username>,
                           password=<password>,
                           prop=prop)

答案 1 :(得分:1)

您需要在Bars表中为A和B提供列:

class Bars(tag:Tag) extends Table[Bar](tag, "BARS") {
  def a = column[String]("A")
  def b = column[String]("B")
  def foo = (a, b) <> (Foo.tupled, Foo.unapply)

  def c = column[String]("C")

  def * = (foo, c) <> (Bar.tupled, Bar.unapply)
}