Here at Gawker Media, we've been making a hard push to convert the entirety of our data layer to use Slick - Typesafe's data access library.
One of the main challenges in working with an ORM is, well, the "M" therein: mapping database rows onto model objects you can use in your application. Since we store all of our model objects as serialized Protocol Buffers, we have an additional layer of conversion to perform.
Here's what a typical model object table looks like:
And the equivalent Slick table declaration:
Some things to take note of here:
- The table is parameterized with type Annotation, which is our model case class (instead of a tuple which you'll commonly see in the Slick documentation)
- the id and entry columns types don't match the raw db column types. We wrap our database ids in an abstracted type over unique keys that are generated from various systems in our stack.
So, what's going on here? Looks like magic. We're actually using some implicit conversions and Slick's mapped projections (ok, so magic).
By placing these two implicit objects in scope:
any time we query or update a row, the column values will be converted to and from these types. Pretty handy.
Following that, we use one of Slick's most valuable features - mapped projections. A projection basically tells Slick which "shape" to make out of the database row (it is analogous to, and is used to form the SELECT clause in the underlying SQL). However, by providing a factory method and extractor (provided by the "serializer" instance in the example) to the <> method of the projection - Slick will do this conversion for you on each query. so:
As you can see - this makes it pretty easy to work with model objects, which are just simple case classes here.