【问题标题】:Scala immutability in persistent storage with Squeryl使用 Squeryl 在持久存储中实现 Scala 不变性
【发布时间】:2017-05-04 21:40:05
【问题描述】:

所以当我阅读Play for Scala 的书时,我发现了书中解释的一些奇怪的东西。这是相关的sn-p:

不过,发生了一些奇怪的事情。如果您使用的是不可变的 类——香草案例类是——你可能会担心当你 发现 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")。如果你的其余部分,这可能会导致糟糕的情况 代码期望您的模型类之一的实例永远不会改变。 为了保护自己免受此类事情的侵害,我们建议您 将我们之前向您展示的插入方法更改为:

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 的人或许可以给出答案?

【问题讨论】:

  • 这不是案例类本身,而是声明为valtable 泛型。它指定访问存储在该表中的对象的规则(实际上表示为案例类)。
  • @piet.t 哈哈,是的,你是对的。我没这么想

标签: scala case-class squeryl


【解决方案1】:

你可以自己查看table方法的定义:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-07
    • 2013-10-19
    • 2011-11-13
    • 1970-01-01
    • 2017-07-25
    • 1970-01-01
    相关资源
    最近更新 更多