Scala immutability in persistent storage with Squeryl
So, while reading the Play for Scala book , I came across something strange that was explained in the book. This is the relevant snippet:
Something strange is going on there. If you are using immutable classes, which are vanilla classes: you may be concerned when you find that Squeryl is updating your object, presumably an immutable id, when you insert an object. This means that if you run the following code,
val myImmutableObject = Product(0, 5010255079763, "plastic coated blue", "standard paperclip, coated with blue plastic") Database.productsTable.insert(myImmutableObject) println(myImmutableObject)
output will suddenly look like this:
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. To protect yourself from this kind of thing, we recommend that you change the insertion methods we showed you earlier:
def insert(product: Product): Product = inTransaction { val defensiveCopy = product.copy productsTable.insert(defensiveCopy) }
My question is 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
the 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 is it possible that a case class, declared as val
, can have one of its fields? Is Squeryl some kind of reflection of some kind to change the field, or is it somehow wrong?
I can't run the examples to check what might be, but someone who has used Squeryl can provide an answer?
source to share
You can check the method definition table
for yourself:
https://github.com/squeryl/squeryl/blob/master/src/main/scala/org/squeryl/Schema.scala#L345
This is a general function that uses reflection to create a table object bound to a given case class. Functions are first-class citizens in Scala, so they can be assigned to val just like anything else.
The last snippet is also an asynchronous function that maps a given argument to a specific modification defined for it.
source to share