Slick vs Anorm – choosing a DB framework for your Scala application

Scala doesn’t offer many DB access libraries. Slick and Anorm seem to be the most popular – both being available in the Play framework. Despite both serving the same purpose, they present completely different approaches. In this post I’d like to present some arguments that might help when choosing between these two.

What is Slick?

Slick is a Functional Relational Mapper. You might be familiar with Object Relational Mappers such as Hibernate. Slick embraces Scala’s functional elements and offers an alternative. Slick authors claim that the gap between relational data and functional programming is much smaller than between object-oriented programming.

Slick allows you to write type safe, SQL-like queries in Scala which are translated into SQL. You define mappings which translate query results into your domain classes (and the other way for INSERT  and UPDATE ). Writing plain SQL is also allowed.

What is Anorm?

Anorm is a thin layer providing database access. It is in a way similar to Spring’s JDBC templates. In Anorm you write queries in plain SQL. You can define your own row parsers which translate query result into your domain classes. Anorm provides a set of handy macros for generating parsers. Additionally, it offers protection against SQL injection with prepared statements.

Anorm authors claim that SQL is the best DSL for accessing relational database and introducing another one is a mistake.

Blocking/non-blocking

As mentioned, Slick API is non-blocking. Slick queries return instances of DBIO  monad which can be later transformed into Future . There are many benefits of a non-blocking API such as improved resilience under load. However, you will not notice these benefits unless your web applications is handling thousands of concurrent connections.

Anorm, as a really thin layer, does not offer a non-blocking API.

Expressibility

Slick’s DSL is very expressive but it will always be less than plain SQL. Anorm’s authors seem to have a point that re-inventing SQL is not easy. Some non-trivial queries are difficult to express and at times you will miss SQL. Obviously, you can always use the plain SQL API in Slick but what’s the point of query type safety if not all of your queries are under control?

Anorm is as expressive as plain SQL. However, passing more exotic query parameters (such as arrays or UUID s) might require spending some time on reading the docs.

Query composability

One of huge strengths of Slick is query composability. Suppose you had two very similar queries:

In Slick, it’s very easy to abstract the common part into a query.

In Anorm, all you can do is textual composition which can get really messy.

Inserts and updates

In Slick you can define two-way mappings between your types and SQL. Therefore, INSERT s are as simply as:

In Anorm you need to write your INSERT s and UPDATE s by hand which is usually a tedious and error-prone task.

Code changes and refactoring

Another important feature of Slick is query type safety. It’s amazing when performing changes to your data model. Compiler will always make sure that you won’t miss any query.

In Anorm nothing will help you detect typos or missing fields in your SQL which will usually make you want to write unit tests for your data access layer.

Conclusion

Slick seems to be a great library packed with very useful features. Additionally, it will most likely save your ass if you need to perform many changes to your data model. However, my point is that it comes at a cost – writing Slick queries is not trivial and the learning curve is quite steep. And you risk that the query you have in mind is not expressible in Slick.

An interesting alternative is to use Slick’s plain SQL API – it gives you some of the benefits (e.g. non-blocking API) but without sacrificing expressability.

As always, it’s a matter of choosing the right tool for purpose. I hope this article will help you to weigh in all arguments.

SBT: how to build and deploy a simple SBT plugin?

Few weeks ago when I was working on my pet project, I wanted to make it an SBT plugin. Since I had to spend some time studying SBT docs, I decided to write a short tutorial explaining how to write and deploy a SBT plugin.

Make sure your project can be built with SBT

First of all, your project needs to be buildable with SBT. This can be achieved simply – any project that follows the specific structure can be built with SBT. additionally, we are going to need a build.sbt  file with the following contents at the top-level:

Note that we are using Scala version 2.10 despite that at the time of writing 2.11 is available. That’s because SBT 0.13 is build against Scala 2.10. You need to make sure that you are using matching versions, otherwise you might get compile errors.

Implement the SBT plugin

Our example plugin is going to add a new command to SBT. Firstly, let’s add the following imports:

Next, we need to extend the AutoPlugin  class. Inside that class we need to create a nested object called autoImport. All SBT keys defined inside this object will be automatically imported into the project using this plugin. In our example we are defining a key for an input task – which is a way to define an SBT command that can accept command line arguments.

Now we need to add an implementation for this task:

And that’s it.

Test the SBT plugin locally

SBT lets us test our plugins locally very easily. Run the following command:

Now we need an example project that will use our plugin. Let’s create an empty project with the following directory structure:

Inside plugins.sbt , let’s put the following code:

Note that this information needs to match organization , name  and version  defined in your plugin. Next, add the following lines to build.sbt:

Make sure that you use the fully qualified name of the plugin object. You can use Scala version older than 2.10 in the consumer project.

Now you can test your plugin. Run the following command:

Note the use of quotes – you are passing the whole command, along with its parameters to SBT.

Make it available to others

If you would like to make your plugin available to other users, you can use OSS Repository Hosting. They are hosting a public Maven repository for open source projects. Packages in this repository are automatically available to SBT users, without further configuration.

The whole procedure is well described here. One of the caveats for me was to change the organization  property to  com.github.miloszpp (I host my project on GitHub). You can’t just use any string here because you need to own the domain – otherwise, you can use the GitHub prefix.