因此,当我阅读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。
最后一个片段也是一个异步函数,它将给定参数映射到为其定义的某些修改。