Typesafe guys certainly gave nice shots embracing projects like play!, akka and Slick.
After finally swallowing the huge change they did on play! itself since its release 1.2.4, I’ve been heavily playing with play! 2.4.3. I like the ability to use different persistent frameworks, but so far, it comes with the cost of sparse documentation and lack of focus on a single well understood solution and all the caveats.
Anyway. Want to share some playground with Slick combined with the power of Futures and functional composition itself. Slick is very powerful and works basically pretending it operates on lists of objects, but behind the scenes it simply generates type safe sql statements.
Futures and composition
Look at the following sniped. This Command
case class is kinda big to paste here, so it is cut. Same for the find method fo this DAO class.
So, the delete
function takes a Future[Command]
, that is, someone before it will actually find a command and give it to this function. All delete
should do is to prepare a query using filter
on commands
table using the familiar filter
approach.
Notice however, that after filtering, there is a map
. This means we will only consider the field whose name is deleted
. Couple lines below you see dbConfig.db.run(q.update(true))
. And this is the point where the sql UPDATE
command is really submitted to the database.
Since we are using flatMap
on Future[Command], this then produces a new future of type Future[Int]
that will hold the number of affected rows once it is completed.
Now take a look at findAndDelete
. It composes the find
function and the delete
, so it is easy for any caller to just call it instead of chain the execution every time.
For comprehension
Slick also offers a monadic approach for querying multiple tables. For example, the for comprehension below:
Generates an SQL:
This is very interesting and shows that the for
notation will not overload your database but simply collaborate to create the query you want.
Promising and returning objects with persisted Id
Please don’t take the following code as canonical, it was just my requirements that led me to do this. But imagine you want to add a new Command
to the database. Instead of returning the number of affected rows or the new id only, you want a copy of the Command
object with the id filled:
This is simply amazing. Notice the returning
function that will make the insertAction returns a Long
upon execution. Remember we want to deliver back a Command
, not the produced id. The solution is to subscribe to this future inside ++
, and once it is completed, you deliver the new immutable Command
: savedPromise.success(command.copy(id = savedId.some))
End
This is far from being a tutorial or complete example of Slick. But gives you a direction of what kind of constructs you can combine. The guys at Underscode.io got deeper posts. But so far, Slick shows to be a very mature solution when it comes to persistence with Scala and relational databases.
Notices it doesn’t provide any caching. You would have to implement yourself. Slicks also offer the possibility to generate code from an existing database, but I personally don’t like this approach.
Take care!
important: >>>
and some
comes from Scalaz. Logger
and dbConfig
comes from the play! project app.