您能否向我解释由于模棱两可的隐式方法,我该如何转换MappedProjection
为ProvenShape
当前失败的方法?
我使用slick-pg支持jsonb
Postgres DB中的类型。
我有一个简单的案例类,我想存储为json,并且有ID列,其值来自案例类。
case class Topic(id: String, title: String) class TopicRow(tag: Tag) extends Table[(String, Topic)](tag, Topic.tableName) { def id = column[String]("id", O.PrimaryKey) def json = column[Topic]("json") def * = (id, json) }
在代码的前面,我在json和case类之间进行了转换
import spray.json._ implicit val TopicColumnType = MappedColumnType.base[Topic, JsValue ]( { obj => obj.toJson }, { json => json.convertTo[Topic] } )
我不喜欢的TopicRow
是它映射到元组。我希望它像这样
class TopicRow(tag: Tag) extends Table[Topic](tag, Topic.tableName) { def id = column[String]("id", O.PrimaryKey) def json = column[Topic]("json") val tupled: ((String, Topic)) => (Topic) = tu => tu._2 val unapply: (Topic) => Option[(String, Topic)] = t => Option((t.id, t)) def * = (id, json) <> (tupled, unapply) }
它无法编译并显示错误
Error:(43, 22) type mismatch; found : slick.lifted.MappedProjection[co.younetworks.medstream.server.models.db.Topic,(String, co.younetworks.medstream.server.models.db.Topic)] required: slick.lifted.ProvenShape[co.younetworks.medstream.server.models.db.Topic]
所以我明确指定了转换的每个步骤,就像这样
def * = { val shape: ProvenShape[Topic] = { val tupled: ((String, Topic)) => (Topic) = tu => tu._2 val unapply: (Topic) => Option[(String, Topic)] = t => Option((t.id, t)) val toToShapedValue: ToShapedValue[(Rep[String], Rep[Topic])] = anyToToShapedValue((id, json)) val mappedProjection: MappedProjection[Topic, (String, Topic)] = toToShapedValue <>(tupled, unapply) ProvenShape.proveShapeOf(mappedProjection) } shape }
那给我错误
Error:(52, 31) ambiguous implicit values: both method mappedProjectionShape in object MappedProjection of type [Level >: slick.lifted.FlatShapeLevel <: slick.lifted.ShapeLevel, T, P]=> slick.lifted.Shape[Level,slick.lifted.MappedProjection[T,P],T,slick.lifted.MappedProjection[T,P]] and method repColumnShape in trait RepShapeImplicits of type [T, Level <: slick.lifted.ShapeLevel](implicit evidence$1: slick.ast.BaseTypedType[T])slick.lifted.Shape[Level,slick.lifted.Rep[T],T,slick.lifted.Rep[T]] match expected type slick.lifted.Shape[_ <: slick.lifted.FlatShapeLevel, slick.lifted.MappedProjection[co.younetworks.medstream.server.models.db.Topic,(String, co.younetworks.medstream.server.models.db.Topic)], U, _] ProvenShape.proveShapeOf(mappedProjection) ^
我怀疑我将映射列的存在与编译器混淆了,但是我不知道如何解决。
好吧,隐式的显式说明很有帮助。它看起来并不漂亮。
class TopicRow(tag: Tag) extends Table[Topic](tag, Topic.tableName) with JsonMarshallers { def id = column[String]("id", O.PrimaryKey) def json = column[Topic]("json") private val fromTuple : ((String, Topic)) => (Topic) = { case (_, value) => value } private val toTuple = (v : Topic) => Option((v.id, v)) def * = ProvenShape.proveShapeOf((id, json) <> (fromTuple, toTuple))(MappedProjection.mappedProjectionShape) }
如果有人知道如何使其短路,请告诉我。