我的代码还有另一个问题:
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的每个属性,有两个要调用的插入。一个实际在某个表中创建新属性,另一个也将该属性的值添加到另一个表中。
那是在:
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)
}
一部分。
现在,如果不,则只需要将属性的值插入到正确的表中,这就是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}")
给了我:
语句:向量(插入“属性”) (“language_id”,“property_id”,“name”)值(?,?,?))Vector(插入 到“node_property”(“node_id”,“property_id”,“value”)值 (?,?,?))
看起来很好。
我很想记录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 ()
答案 0 :(得分:1)
看起来最终的答案是重组一下:
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
方法。
我想知道transactionally
如果内部for
理解中发生了什么,会发生什么。我想根据我对文档的解释 - http://slick.lightbend.com/doc/3.2.1/dbio.html#transactions-and-pinned-sessions
嵌套的事务性操作只需在现有事务中执行,无需额外的保存点。