用分支链接 DBIOAction,一个分支什么都不做
Chaining DBIOAction with branching, one branch does nothing
来自
我的代码还有一个问题:
def add(languageCode: String,
typeId: Long,
properties: Seq[Property]): Unit = {
val dbAction = (
for{
nodeId <- (nodes.all returning nodes.all.map(_.id)) += Node(typeId)
language <- (languages.all filter (_.code === languageCode)).result.head
_ <- DBIO.seq(properties.map
{
property =>
val id = property.id
val name = property.key
val value = property.value
if(id == 0) {
val currentPropId: FixedSqlAction[Option[Long], h2Profile.api.NoStream, Effect.Read] = this.properties.all.map(_.id).max.result
val propertyId = (this.properties.all returning this.properties.all.map(_.id)) += Property(language.id.get, currentPropId + 1, name)
nodeProperties.all += NodeProperty(nodeId, 2, value)
} else {
nodeProperties.all += NodeProperty(nodeId, id, value)
}
}: _*)
} yield()).transactionally
db.run(dbAction)
}
1)
基本思想是,如果每个 属性 的 id 为 0,则有两个插入要调用。一个在某些 table 中实际创建新的 属性,另一个也将那个 属性 的值添加到另一个 table.
那是在:
if(id == 0) {
val currentPropId: Rep[Option[Long]] = this.properties.all.map(_.id).max
// FIXME get rid of hardcoded languageId
val DUMMY_LANGUAGE_ID = 1
val propertyId = (this.properties.all returning this.properties.all.map(_.id)) += Property(DUMMY_LANGUAGE_ID, currentPropId + 1, name)
nodeProperties.all += NodeProperty(nodeId, 2, value)
}
部分。
现在,如果不是的话,只需要将属性的值插入到正确的table,就是这样else
部分用于.
我面临的问题是,对于 id == 0
什么都没有插入的情况。
我也这样试过:
if(id == 0) {
val nextPropId: Rep[Option[Long]] = this.properties.all.map(_.id).max
// FIXME get rid of hardcoded languageId
val propertyId = (this.properties.all returning this.properties.all.map(_.id)) += Property(1, 10, name)
val nodeProperty = nodeProperties.all += NodeProperty(nodeId, 2, value)
propertyId andThen nodeProperty
}
但无济于事。
else
部分工作得很好。我在这里错过了什么?
编辑:
因为有人问我。
val propertyId = (this.properties.all returning this.properties.all.map(_.id)) += Property(language.id.get, 10, name)
val nodeProperty = nodeProperties.all += NodeProperty(nodeId, 2, value)
log.info(s"Statements: ${propertyId.statements}")
log.info(s"${nodeProperty.statements}")
给我:
Statements: Vector(insert into "properties"
("language_id","property_id","name") values (?,?,?)) Vector(insert
into "node_property" ("node_id","property_id","value") values
(?,?,?))
看起来还不错。
我也很想记录 dbAction
本身的内容,但由于它是 DBIOAction
我没有找到一种有意义的方式来做到这一点。
如果我将日志记录设置为跟踪,我会得到:
22:18:16:016 - [debug] s.c.QueryCompilerBenchmark - ------------------- Phase: Time ---------
22:18:16:016 - [debug] s.c.QueryCompilerBenchmark - assignUniqueSymbols: 0.456428 ms
22:18:16:016 - [debug] s.c.QueryCompilerBenchmark - inferTypes: 0.089135 ms
22:18:16:016 - [debug] s.c.QueryCompilerBenchmark - insertCompiler: 0.292443 ms
22:18:16:016 - [debug] s.c.QueryCompilerBenchmark - codeGen: 0.534494 ms
22:18:16:016 - [debug] s.c.QueryCompilerBenchmark - TOTAL: 1.372500 ms
22:18:16:016 - [debug] s.b.B.action - #5: Rollback
不知道为什么最后一行说 Rollback
因为之前的所有内容(相当多)对我来说似乎没问题。
edit2:
看来我终于有了:
val dbAction = for {
nodeId <- (nodes.all returning nodes.all.map(_.id)) += Node(typeId)
languageId <- (languages.all filter (_.code === languageCode)).map(_.id).result.head
_ <- DBIO.seq(properties.values.map
{
property =>
val id = property.id
val name = property.key
val value = property.value
if(id == 0) {
for {
currentPropId <- this.properties.all.map(_.id).max.result
propertyId <- (this.properties.all returning this.properties.all.map(_.id)) += Property(languageId, currentPropId.get + 1, name)
_ <- this.nodeProperties.all += NodeProperty(nodeId, propertyId, value)
} yield ()
} else {
this.nodeProperties.all += NodeProperty(nodeId, id, value)
}
}: _*)
} yield ()
看来最后的答案是重组一下:
val dbAction = for {
nodeId <- (nodes.all returning nodes.all.map(_.id)) += Node(typeId)
languageId <- (languages.all filter (_.code === languageCode)).map(_.id).result.head
_ <- DBIO.seq(properties.values.map
{
property =>
val id = property.id
val name = property.key
val value = property.value
if(id == 0) {
for {
currentPropId <- this.properties.all.map(_.id).max.result
propertyId <- (this.properties.all returning this.properties.all.map(_.id)) += Property(languageId, currentPropId.get + 1, name)
_ <- this.nodeProperties.all += NodeProperty(nodeId, propertyId, value)
} yield ()
} else {
this.nodeProperties.all += NodeProperty(nodeId, id, value)
}
}: _*)
} yield ()
我很想看到其他解决方案,但这是我在又一次长时间的反复试验后找到的解决方案。我仍然不确定为什么我无法使用 andThen
方法。
而且我想知道如果在内部 for
理解中发生某些事情,transactionally
会发生什么。我想根据我对文档的解释它不会起作用 - http://slick.lightbend.com/doc/3.2.1/dbio.html#transactions-and-pinned-sessions
Nested transactionally actions simply execute inside the existing transaction without additional savepoints.
来自
我的代码还有一个问题:
def add(languageCode: String,
typeId: Long,
properties: Seq[Property]): Unit = {
val dbAction = (
for{
nodeId <- (nodes.all returning nodes.all.map(_.id)) += Node(typeId)
language <- (languages.all filter (_.code === languageCode)).result.head
_ <- DBIO.seq(properties.map
{
property =>
val id = property.id
val name = property.key
val value = property.value
if(id == 0) {
val currentPropId: FixedSqlAction[Option[Long], h2Profile.api.NoStream, Effect.Read] = this.properties.all.map(_.id).max.result
val propertyId = (this.properties.all returning this.properties.all.map(_.id)) += Property(language.id.get, currentPropId + 1, name)
nodeProperties.all += NodeProperty(nodeId, 2, value)
} else {
nodeProperties.all += NodeProperty(nodeId, id, value)
}
}: _*)
} yield()).transactionally
db.run(dbAction)
}
1) 基本思想是,如果每个 属性 的 id 为 0,则有两个插入要调用。一个在某些 table 中实际创建新的 属性,另一个也将那个 属性 的值添加到另一个 table.
那是在:
if(id == 0) {
val currentPropId: Rep[Option[Long]] = this.properties.all.map(_.id).max
// FIXME get rid of hardcoded languageId
val DUMMY_LANGUAGE_ID = 1
val propertyId = (this.properties.all returning this.properties.all.map(_.id)) += Property(DUMMY_LANGUAGE_ID, currentPropId + 1, name)
nodeProperties.all += NodeProperty(nodeId, 2, value)
}
部分。
现在,如果不是的话,只需要将属性的值插入到正确的table,就是这样else
部分用于.
我面临的问题是,对于 id == 0
什么都没有插入的情况。
我也这样试过:
if(id == 0) {
val nextPropId: Rep[Option[Long]] = this.properties.all.map(_.id).max
// FIXME get rid of hardcoded languageId
val propertyId = (this.properties.all returning this.properties.all.map(_.id)) += Property(1, 10, name)
val nodeProperty = nodeProperties.all += NodeProperty(nodeId, 2, value)
propertyId andThen nodeProperty
}
但无济于事。
else
部分工作得很好。我在这里错过了什么?
编辑:
因为有人问我。
val propertyId = (this.properties.all returning this.properties.all.map(_.id)) += Property(language.id.get, 10, name)
val nodeProperty = nodeProperties.all += NodeProperty(nodeId, 2, value)
log.info(s"Statements: ${propertyId.statements}")
log.info(s"${nodeProperty.statements}")
给我:
Statements: Vector(insert into "properties" ("language_id","property_id","name") values (?,?,?)) Vector(insert into "node_property" ("node_id","property_id","value") values (?,?,?))
看起来还不错。
我也很想记录 dbAction
本身的内容,但由于它是 DBIOAction
我没有找到一种有意义的方式来做到这一点。
如果我将日志记录设置为跟踪,我会得到:
22:18:16:016 - [debug] s.c.QueryCompilerBenchmark - ------------------- Phase: Time ---------
22:18:16:016 - [debug] s.c.QueryCompilerBenchmark - assignUniqueSymbols: 0.456428 ms
22:18:16:016 - [debug] s.c.QueryCompilerBenchmark - inferTypes: 0.089135 ms
22:18:16:016 - [debug] s.c.QueryCompilerBenchmark - insertCompiler: 0.292443 ms
22:18:16:016 - [debug] s.c.QueryCompilerBenchmark - codeGen: 0.534494 ms
22:18:16:016 - [debug] s.c.QueryCompilerBenchmark - TOTAL: 1.372500 ms
22:18:16:016 - [debug] s.b.B.action - #5: Rollback
不知道为什么最后一行说 Rollback
因为之前的所有内容(相当多)对我来说似乎没问题。
edit2:
看来我终于有了:
val dbAction = for {
nodeId <- (nodes.all returning nodes.all.map(_.id)) += Node(typeId)
languageId <- (languages.all filter (_.code === languageCode)).map(_.id).result.head
_ <- DBIO.seq(properties.values.map
{
property =>
val id = property.id
val name = property.key
val value = property.value
if(id == 0) {
for {
currentPropId <- this.properties.all.map(_.id).max.result
propertyId <- (this.properties.all returning this.properties.all.map(_.id)) += Property(languageId, currentPropId.get + 1, name)
_ <- this.nodeProperties.all += NodeProperty(nodeId, propertyId, value)
} yield ()
} else {
this.nodeProperties.all += NodeProperty(nodeId, id, value)
}
}: _*)
} yield ()
看来最后的答案是重组一下:
val dbAction = for {
nodeId <- (nodes.all returning nodes.all.map(_.id)) += Node(typeId)
languageId <- (languages.all filter (_.code === languageCode)).map(_.id).result.head
_ <- DBIO.seq(properties.values.map
{
property =>
val id = property.id
val name = property.key
val value = property.value
if(id == 0) {
for {
currentPropId <- this.properties.all.map(_.id).max.result
propertyId <- (this.properties.all returning this.properties.all.map(_.id)) += Property(languageId, currentPropId.get + 1, name)
_ <- this.nodeProperties.all += NodeProperty(nodeId, propertyId, value)
} yield ()
} else {
this.nodeProperties.all += NodeProperty(nodeId, id, value)
}
}: _*)
} yield ()
我很想看到其他解决方案,但这是我在又一次长时间的反复试验后找到的解决方案。我仍然不确定为什么我无法使用 andThen
方法。
而且我想知道如果在内部 for
理解中发生某些事情,transactionally
会发生什么。我想根据我对文档的解释它不会起作用 - http://slick.lightbend.com/doc/3.2.1/dbio.html#transactions-and-pinned-sessions
Nested transactionally actions simply execute inside the existing transaction without additional savepoints.