因此,当我阅读Play for Scala书时,我发现书中解释的奇怪之处。这是相关的代码段:


但是,发生了一些奇怪的事情。如果您使用的是不可变的
类(即普通案例类),您可能会担心
发现Squeryl更新了您的对象的不可变ID
插入对象时的字段。也就是说,如果执行
以下代码,

val myImmutableObject = Product(0, 5010255079763,
  "plastic coated blue", "standard paperclip, coated with blue plastic")
Database.productsTable.insert(myImmutableObject)
println(myImmutableObject)


输出将意外地是这样的:Product(13, 5010255079763, "plastic coated blue", "standard paperclip, coated with blue plastic")。如果您的其余部分可能导致不良情况
代码期望您的模型类之一的实例永远不变。
为了保护自己免受此类伤害,我们建议您
更改我们之前向您展示的insert方法:

def insert(product: Product): Product = inTransaction {
    val defensiveCopy = product.copy
    productsTable.insert(defensiveCopy)
}



我的问题是,鉴于产品类的定义如下:

import org.squeryl.KeyedEntity

case class Product(
    id: Long,
    ean: Long,
    name: String,
    description: String) extends KeyedEntity[Long]


Database对象的定义如下:

import org.squeryl.Schema
import org.squeryl.PrimitiveTypeMode._
object Database extends Schema {
    val productsTable = table[Product]("products")
    ...

    on(productsTable) { p => declare {
        p.id is(autoIncremented)
    }}
}


那么,声明为val的案例类如何更改其字段之一呢? Squeryl是使用某种形式的反射来更改字段还是书被某种方式弄错了?

我无法运行示例来验证情况如何,但是使用Squeryl的人也许可以给出答案?

最佳答案

您可以自己检查table方法的定义:

https://github.com/squeryl/squeryl/blob/master/src/main/scala/org/squeryl/Schema.scala#L345

这是一个通用函数,它确实使用反射来实例化绑定到给定案例类的Table对象。函数是Scala中的一等公民,因此可以像其他任何函数一样将其分配给val。

最后一个片段也是一个异步函数,它将给定参数映射到为其定义的某些修改。

07-24 13:17