So as I am reading the Play for Scala book, I came across something odd that was explained in the book. This is the relevant snippet:
There's something strange going on, though. If you're using immutable classes—which vanilla case classes are—you might be worried when you discover that Squeryl updates your object's supposedly immutable id field when you insert the object. That means that if you execute the following code,
val myImmutableObject = Product(0, 5010255079763, "plastic coated blue", "standard paperclip, coated with blue plastic") Database.productsTable.insert(myImmutableObject) println(myImmutableObject)
the output will unexpectedly be something like:
Product(13, 5010255079763, "plastic coated blue", "standard paperclip, coated with blue plastic")
. This can lead to bad situations if the rest of your code expects an instance of one of your model classes to never change. In order to protect yourself from this sort of stuff, we recommend you change the insert methods we showed you earlier into this:def insert(product: Product): Product = inTransaction { val defensiveCopy = product.copy productsTable.insert(defensiveCopy) }
My question is, given that the product class is defined like this:
import org.squeryl.KeyedEntity
case class Product(
id: Long,
ean: Long,
name: String,
description: String) extends KeyedEntity[Long]
Database
object is defined like this:
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)
}}
}
How then is it possible that a case class declared as val
can have one of its fields changed? Is Squeryl using reflection of some sort to change the field or is the book mistaken somehow?
I am not able to run the examples to verify what the case might be, but someone who has used Squeryl can perhaps give an answer?