Easiest Way To Map Optional Nested Case Class with Slick in Scala


Few days ago, I had a scenario, in which I was supposed to map optional nested case class in slick using Scala.

case class Employee(emdId:String,name: String, record: Option[Record])
case class Record(subject: String, mark: Int)

I was trying to do this mapping the way, I have explained below.

class EmployeeSlickMapping(tag: Tag) extends Table[Employee](tag, "Employee") {
  def emdId = column[String]("emdId")
  def name = column[String]("name")
  def subject = column[String]("subject", O.Nullable)
  def mark = column[Int]("mark", O.Nullable)
  def record = (subject, mark) <> (Record.tupled, Record.unapply)
  def * = (emdId,name, address) <> (User.tupled, User.unapply)
}

But I was getting below compilation error.

Multiple markers at this line
    - No matching Shape found. Slick does not know how to map the given types. Possible causes: T in Table[T] does not match your * projection. Or you use an unsupported
     type in a Query (e.g. scala List). Required level: scala.slick.lifted.FlatShapeLevel Source type: (scala.slick.lifted.Column[String], scala.slick.lifted.Column[String],
     scala.slick.lifted.MappedProjection[platform3.models.mail.Record,(String, Int)]) Unpacked type: (String, String, Option[platform3.models.mail.Record]) Packed type: Any
    - not enough arguments for method <>: (implicit evidence$2: scala.reflect.ClassTag[platform3.models.mail.Employee], implicit shape: scala.slick.lifted.Shape[_ <:
     scala.slick.lifted.FlatShapeLevel, (scala.slick.lifted.Column[String], scala.slick.lifted.Column[String], scala.slick.lifted.MappedProjection[platform3.models.mail.Record,
     (String, Int)]), (String, String, Option[platform3.models.mail.Record]), _])scala.slick.lifted.MappedProjection[platform3.models.mail.Employee,(String, String,
     Option[platform3.models.mail.Record])]. Unspecified value parameter shape.
    - No matching Shape found. Slick does not know how to map the given types. Possible causes: T in Table[T] does not match your * projection. Or you use an unsupported
     type in a Query (e.g. scala List). Required level: scala.slick.lifted.FlatShapeLevel Source type: (scala.slick.lifted.Column[String], scala.slick.lifted.Column[String],
     scala.slick.lifted.MappedProjection[platform3.models.mail.Record,(String, Int)]) Unpacked type: (String, String, Option[platform3.models.mail.Record]) Packed type: Any
    - Implicit conversions found: => anyToToShapedValue()
    - not enough arguments for method <>: (implicit evidence$2: scala.reflect.ClassTag[platform3.models.mail.Employee], implicit shape: scala.slick.lifted.Shape[_ <:
     scala.slick.lifted.FlatShapeLevel, (scala.slick.lifted.Column[String], scala.slick.lifted.Column[String], scala.slick.lifted.MappedProjection[platform3.models.mail.Record,
     (String, Int)]), (String, String, Option[platform3.models.mail.Record]), _])scala.slick.lifted.MappedProjection[platform3.models.mail.Employee,(String, String,
     Option[platform3.models.mail.Record])]. Unspecified value parameter shape.

After beating my head two days, I found a solution by adding custom mapping.

class EmployeeSlickMapping(tag: Tag) extends Table[Employee](tag, "Employee") {
  def emdId = column[String]("emdId")
  def name = column[String]("name")
  def subject = column[String]("subject")
  def mark = column[Int]("mark")
  def record = (subject.?, mark.?).<>[Option[Record], (Option[String], Option[Int])](
    { mappedRecord =>
      mappedRecord match {
        case (Some(subject), Some(mark)) => Some(Record(subject, mark))
        case _ => None
      }
    },
    { result =>
      result match {
        case rec: Option[Record] => Some(rec.map(_.subject), rec.map(_.mark))
      }
    })
  def * = (emdId, name, record) <> (Employee.tupled, Employee.unapply)
}

It worked and now I am able to compile and run my code.

Advertisements

About Ayush Mishra

Ayush is the Sr. Software Consultant @ Knoldus Software LLP. In his 5 years of experience he has become developer with proven experience in architecting and developing web applications. Ayush has a Masters in Computer Application from U.P. Technical University, Ayush is a strong-willed and self-motivated professional who takes deep care in adhering to quality norms within projects. He is capable of managing challenging projects with remarkable deadline sensitivity without compromising code quality. .
This entry was posted in Java, Scala and tagged , . Bookmark the permalink.

2 Responses to Easiest Way To Map Optional Nested Case Class with Slick in Scala

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s