1

假设我有一个这样的实体类:

case class MyEntity(some_flag: Boolean) extends KeyedEntity[Long]

我想使用 Squeryl 执行以下 SQL 更新:

update table_name set some_flag = not some_flag where id = 1

执行此操作的相关 Squeryl 语句是什么?我已经试过了

def toggleFlag(id: Long) = inTransaction {
    update(table)(entity =>
        where(entity.id === id)
        set(entity.some_flag := !entity.some_flag)
    )
}

但这对数据库没有任何影响。

更新 2: Squeryl文档给出了将整数值增加 1 的部分更新示例:

update(songs)(s =>
  where(s.title === "Watermelon Man")
  set(s.title := "The Watermelon Man",
      s.year  := s.year.~ + 1)
)  

更新:

我将 Squeryl 0.9.5-6 与 Scala 2.10 和 Play 一起使用!2.1

4

1 回答 1

1

我用你的例子做了一个小代码项目。问题是 squeryl 序列化更新,但它“吞下了”(!),产生以下 SQL:

 update MyEntity set
 some_flag = (some_flag)

基本上,squeryl 在后台构建一个由操作组成的树,然后将其序列化为一个字符串,该字符串将发送到 SQL 适配器。

一般来说,我检查它隔离更新语句并打印它(就像 squeryl 一样):

    // From __update, Table.scala
    val dba = Session.currentSession.databaseAdapter
    val sw = new StatementWriter(dba)
    val o0 = _callbacks.beforeUpdate(o.asInstanceOf[AnyRef]).asInstanceOf[T]
    dba.writeUpdate(o0, this, sw, checkOCC)

在我的类中复制代码(出于调试目的)或直接在 Table.scala 中设置断点

要隔离该语句,只需排除更新的第二部分:

val s = ((entity: InsertTypeHere) =>
      where(entity.id === id)
      set(entity.some_flag := not entity.some_flag))

多亏了这个“技巧”,我发现对 some_flag 的引用被正确地转换为 java.lang.Boolean 类型的 SelectElementReference,但是 (!) 没有被转换为 PrefixOperator。对我来说这似乎是一个 squeryl 错误,但让我看看是否可以从您的代码中“修复”它。

更新:

挖掘 squeryl 代码,似乎确实缺少“非”运算符。幸运的是,很容易自己添加回来!

     class NotExpression(val ast: ExpressionNode)(implicit val mapper: OutMapper[BooleanType])
        extends PrefixOperatorNode(ast, "not ", false)
                with LogicalBoolean with NestedExpression with TypedExpressionNode[BooleanType]

     def mynot(b: BooleanExpression[BooleanType]) = new NotExpression(b)

     transaction {
          update(table)(t => where(t.id === 3) set (t.some_flag := mynot(t.some_flag)))
     }

至少在您的情况下,这会产生正确的 SQL。我将向 squeryl 提交补丁并征求意见。

于 2013-03-06T09:34:08.163 回答