我理解在使用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
答案 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)
}