1
私はSlick 3の機能モデルで精神ブロックに直面していると確信していますが、Slick 3のオプションの従属dbステップをトランザクション的にどのようにシーケンスするかは分かりません。特に、オプションの)外部キーと私はそれが挿入された従属レコードのID(もしあれば、null)に設定されることを望みます。つまり、おおよそ次のようになります。slick 3でオプションのdbステップを処理する方法は?
if (x is non null)
start transaction
id = insert x
insert y(x = id)
commit
else
start transaction
insert y(x = null)
commit
もちろん、私は選択肢の周りに大きい場合はありません。 Option []を持たない依存関係は(比較的)単純ですが、オプションが私を投げています。
正確なサンプルコード(サンのインポート)が続きます。この例では、yがNoneである場合とそうでない場合の両方で、x(a)とy(b)の両方を同じトランザクションに保存する方法が問題です。すべての関連するCにはオプションではないB参照があるので、Y自体を保存するだけでも簡単ですが、Aの任意の参照に対処するのは不明です(私にとって)。
object test {
implicit val db = Database.forURL("jdbc:h2:mem:DataTableTypesTest;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver")
/* Data model */
case class A(id: Long, b: Option[Long], s: String)
class As(tag: Tag) extends Table[A](tag, "As") {
def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)
def b = column[Option[Long]]("B")
def s = column[String]("S")
def * = (id, b, s) <> (A.tupled, A.unapply)
}
val as = TableQuery[As]
case class B(id: Long, s: String)
class Bs(tag: Tag) extends Table[B](tag, "Bs") {
def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)
def s = column[String]("S")
def * = (id, s) <> (B.tupled, B.unapply)
}
val bs = TableQuery[Bs]
case class C(id: Long, b: Long, s: String)
class Cs(tag: Tag) extends Table[C](tag, "Cs") {
def id = column[Long]("ID", O.PrimaryKey, O.AutoInc)
def b = column[Long]("B")
def s = column[String]("S")
def * = (id, b, s) <> (C.tupled, C.unapply)
}
val cs = TableQuery[Cs]
/* Object model */
case class X(id: Long, s: String, y: Option[Y])
case class Y(id: Long, s: String, z: Set[Z])
case class Z(id: Long, s: String)
/* Mappers */
def xToA(x: X, bId: Option[Long]): A = { A(x.id, bId, x.s) }
def yToB(y: Y): B = { B(y.id, y.s) }
def zToC(z: Z, bId: Long): C = { C(z.id, bId, z.s) }
/* Given */
val example1 = X(0, "X1", Some(Y(0, "Y1", Set(Z(0, "Z11"), Z(0, "Z12")))))
val example2 = X(0, "X2", Some(Y(0, "Y2", Set())))
val example3 = X(0, "X3", None)
Await.result(db.run((as.schema ++ bs.schema ++ cs.schema).create), 10.seconds)
val examples = Seq(example1, example2, example3)
for (example <- examples) {
val saveY = (for { y <- example.y }
yield (for {
id <- (bs returning bs.map(_.id)) += yToB(y)
_ <- cs ++= y.z.map(zToC(_, id))
} yield id) transactionally)
if (saveY.isDefined) Await.result(db.run(saveY.get), 10.seconds)
}
println(Await.result(
db.run(
(for { a <- as } yield a).result
),
10.seconds
))
println(Await.result(
db.run(
(for { b <- bs } yield b).result
),
10.seconds
))
println(Await.result(
db.run(
(for { c <- cs } yield c).result
),
10.seconds
))
}
ありがとうございます。今精神的に消化する:) –