Defining a projection to map to nested case classes

I have case classes:

case class PolicyHolder(id : String, firstName : String, lastName : String) case class Policy(address : Future[Address], policyHolder : Future[PolicyHolder], created : RichDateTime, duration : RichDuration ) 

Then I have a smooth policy-specific scheme

 class PolicyDAO(tag: Tag) extends Table[Policy](tag, "POLICIES") with DbConfig { def address = column[String]("ADDRESS", O.PrimaryKey) def policyHolder = foreignKey("POLICY_HOLDER_FK", address, TableQuery[PolicyHolderDAO])(_.id) def created = column[RichDateTime]("CREATED") def duration = column[String]("DURATION") def * = (address, policyHolder, created, duration) <> (Policy.apply, Policy.unapply) } 

The best way to correctly define this projection is to map the policyHolder field within the class of the Policy class from the value of the foreign key to the actual instance of the case policyHolder class.

+7
scala
source share
1 answer

Our solution to this problem is to put the foreign key identifier in the case class, and then use the lazy val or def (the latter may be supported by the cache) to retrieve the record using the key. This assumes that your PolicyHolder is stored in a separate table - if they are denormalized, but you want to treat them as separate case classes, then you can have the lazy val / def in Policy to build a new case class instead of retrieving the record using a foreign key.

 class PolicyDAO(tag: Tag) extends Table[Policy](tag, "POLICIES") with DbConfig { def address = column[String]("ADDRESS", O.PrimaryKey) def policyHolderId = column[String]("POLICY_HOLDER_ID") def created = column[RichDateTime]("CREATED") def duration = column[String]("DURATION") def * = (address, policyHolderId, created, duration) <> (Policy.apply, Policy.unapply) } case class Policy(address : Future[Address], policyHolderId : Future[String], created : RichDateTime, duration : RichDuration ) { lazy val policyHolder = policyHolderId.map(id => PolicyHolderDAO.get(id)) } 

We also used a common set of create / update / delete methods to account for nesting, so when a Policy PolicyHolder , its internal PolicyHolder will also be committed; we used the CommonDAO class, which extended the Table and had prototypes for the create / update / delete methods, and then all the DAOs extended the CommonDAO instead of the Table and redid the creation / update / delete if necessary.


Edit: To reduce errors and reduce the number of templates that we had to write, we used the Slick code generation tool - this way CRUD operations can be automatically generated from the circuit

+3
source share

All Articles