Slick3野郎の備忘録2
前回はSlick3の基本的な実装方法を紹介しました
今回は少し踏み込みます
解決したいこと
その1
アクションの中での条件分岐したい
その2
list(Seq)をforでぶん回しつつ
AutoIncrementなPrimarykeyをもつTalbleに一件登録登録しーの
そのreturningIdをつかって関連テーブルも同時に作成・更新しーの
さらには他の更新処理も一気にやるために、あれもこれもアクション合成したい
特にバッチ処理などではそんなクソみたいな場面はよくあると思います
方針
Await.result, Await.readyは使わない
全部を1トランザクションでやる
Slick3は一気に10,000件程度生SQLを投げると落ちると言うウワサは気にしない
コード
// サンプル用の変数
val dummyByte = 1.toByte
val dummyString = "dummy"
val dummyByte = 1.toByte
/**
* アクション合成中での条件分岐例
*/
def test(id: Long): DBIO[Unit] = {
val action = for {
// SampleTable を探す
opt <- SampleTable.filter(_.id === row.id).result.headOption
// SampleTableがいたら実行する
_ <- opt.fold[DBIO[Int]](DBIO.successful(1))(x =>
// SampleTable を 無駄に複製してみる
SampleTable += x
)
// SampleTableがいたら実行する
_ <- iPOp.fold[DBIO[Int]](DBIO.successful(1))(x =>
//SampleTable の deleteFlg を 無駄に更新してみる
SampleTable.filter(_.id === ip.id).update(ip.copy(deleteFlg = Some(false))))
} yield ()
action.transactionally
}
/**
* イテレーションを使ってアクション合成
*/
def test2(saveList: Seq[Long]) = {
// 1件を処理する関数を定義
def nested(saveId: Long) = {
for {
newId <- UserAccount returning UserAccount.map(_.id) += makeDummySampleTable1Row(saveId)
_ <- InfluPassbook += makeDummySampleTable2Row(newId)
}yield{}
}
// 普通にforyieldの結果でDBIO.sequenceを生成するアクションを定義
val seqActions = DBIO.sequence(
for(row <- saveList)yield{
nested(row)
}
)
// 実行
db.run(seqActions.transactionally)
// ちみにandThenを用いると アクション合成 + アクション合成なんてのもサクッとできる
//dbMain.run((seqActions andThen seqActions).transactionally)
}
private def makeSampleTable1(id: Long) = {
SampleTable1Row(
name = dummyString
,prisonerNumber = id
,prisonertype = Some(dummyByte)
,deleteFlg = Some(false)
)
}
private def makeSampleTable2(id: Long) = {
SampleTable2Row(
makeSampleTable1Id = id
,cellType = dummyByte
,deleteFlg = Some(false)
)
}