Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala Slick and complex types in my database

Tags:

scala

slick

I am very new to both Scala and Slick and in trying to learn it I am writing a small application that works with a simple database.

Most of my previous experience comes from .Net and the Entity Framework so I was wondering if like in Entity Framework with the ComplexType attribute if Slick would allow me to do the same.

Basically one of my tables is a 1-1 relationship and for some of them I would prefer to just create an object and use it as a complex type. Obviously in the database this is just extra columns on the table, but I was wondering if Slick could map those columns to an object in my Table class. See example below.

I will use a Blog entry example.

My main class that extends Table is BlogEntry and it contains the text of the entry. Then say I wanted in that class another class called EntryDetails that contained the time the entry was posted and the time it was last updated.

In the database all those fields will be in the same table, but when read in it will be one object containing the other object. Is this possible with Slick?

like image 597
twreid Avatar asked Aug 14 '13 14:08

twreid


1 Answers

I think that this solves your problem

 trait Mapping {
  //Need to change JdbcDriver to the driver that you will use in your code (MySql, Postgres, etc)

  import scala.slick.driver.JdbcDriver.profile.simple._

  // Models
  case class EntryDetails(createDate: Option[DateTime] = None, updateDate: Option[DateTime] = None)

  case class Entry(id: Int, text: String, details: EntryDetails)

  //Implicit Joda Mappers for datetime columns
  implicit def timestamp2dateTime = MappedColumnType.base[DateTime, Timestamp](
    dateTime => new Timestamp(dateTime.getMillis),
    date => new DateTime(date))

  //Table mapping
  class Entries(tag: Tag) extends Table[Entry](tag, "entry") {
    def entryDetails = (createDate, updateDate) <>(EntryDetails.tupled, EntryDetails.unapply)

    def * = (id, text, entryDetails) <>(Entry.tupled, Entry.unapply)

    val id: Column[Int] = column[Int]("id")
    val text: Column[String] = column[String]("text")
    val createDate: Column[Option[DateTime]] = column[Option[DateTime]]("createDate")
    val updateDate: Column[Option[DateTime]] = column[Option[DateTime]]("updateDate")
  }

  //Table query, used in slick 2.0 for querying a table
  lazy val EntryTableQuery = TableQuery[Entries]
}

I included everything in a trait Mapping, to pack the code for your answer. As far as I understood, you want to map a table to two objects, one inside the other, this can be achieved by creating another mapping method, here called entryDetails, that map the table queries to the EntryDetails model object. Then you can add this mapping method to your object mapping, the * method. The method entryDetails will be just another parameter of that mapping method.

like image 176
dirceusemighini Avatar answered Oct 03 '22 00:10

dirceusemighini