In learning play-slick, and setting up model classes that are eventually saved to PostgreSQL, I see this pattern (code below). There's a simple case class that acts as a model, and then something that extends Table that handles the relational mapping.
case class Cat(name: String, color: String)
/* Table mapping
*/
class CatsTable(tag: Tag) extends Table[Cat](tag, "CAT") {
def name = column[String]("name", O.PrimaryKey)
def color = column[String]("color", O.NotNull)
def * = (name, color) <> (Cat.tupled, Cat.unapply _)
}
This strikes me in many common cases to be a bunch of unnecessary boilerplate, but I'm just learning so I don't know what I'm missing here. Is there an easier way to start with the case class Cat
and end up with an object I can use to CRUD instances of Cat in the database? E.g. it seems unnecessary to specify that an attribute of type String
should end up being a column[String]
, and so on. In other frameworks, I might have to add an annotation or something to indicate which I want to be a primary key, or non-nullable, but I wouldn't really write a separate mapping. By hand-writing these mappings, I'm mostly just spending more time and getting the opportunity to screw it up in subtle ways for otherwise simple cases.
What I'd ideally like is to start with case class Cat
, sprinkle magic framework dust on it, and get a CatsTable
with reasonable defaults, which I could override/customize as necessary.
When I'm searching for docs on this, I usually end up back at schema code generation but this seems backwards; I don't want to generate the table mappings from an existing/populate RDBMS, I want to start from scratch.
http://getquill.io/
, which needs less boilerplate than Slick, and also provides a choice of jdbc or truly async db calls. As of June 2017, it feels somewhat less polished - eg I'm currently using a combination of Slick and Quill since I can't get the latter to call stored procedures. – thund