Arrange the Demo
using scala

Repository Pattern/Generic DAO Implementation in Scala using Slick

We, at Reactore, switched from Java to Scala over a year ago. We are utilising most of the cutting edge technologies in the Scala Ecosystem. We always strive to write better, re-usable and more efficient code. In this blog, we are demonstrating how to implement a generic DAO pattern in Scala using Slick, which is an excerpt from Reactore’s core framework. We use both the repository pattern and generic DAO pattern in this blog.

The term, Repository Pattern is very closely associated with DDD. In DDD, the models are represented in a business rather than a technical manner.

When developing an enterprise application, with hundreds of tables, the best approach is to follow a particular style for development. Repository patterns help to manage a huge number of operations easily. It also provides an abstraction over multiple things, for ex. getting connection, filtering records etc.
This also ensures that the same standards are used across by the team and any new team can easily adapt and understand the code.

We have been using the repository pattern(both for Java and Scala) for quite some time now. Here are a few ways in which the repository pattern has assisted us at Reactore :-

  • Enforce uniform pattern/implementation, especially useful in enterprise level applications
  • No need to write code for general/common operations which makes the development easier and quicker
  • A centralized mechanism to handle all the common operations
  • Easy to add/remove new common functionality without every implementer needing to explicitly implement it
  • Provides a better layer of abstraction

Now we will demonstrate how to implement generic repository for handling database operations. We are using Slick and PostgreSQL database for the samples.

First, decide all are the methods/operations should be allowed on each table.

For e.g. assume that we need to have a uniform CRUD operation method. The methods can be like the below:

  • getAll: Gets all the records from the table
  • getById: Gets the record with the primary key id provided
  • filter: Filter the table records with provided conditions
  • save: Insert a record to the table
  • updateById: Update an existing record
  • deleteById: Delete a record by its primary key

Now let’s see how to write a generic class which can implement all the above methods.

First of all, we need to create a generic trait and Slick abstract class which every other table entity needs to implement.

In our application, we are only doing logical delete, which will be marked by the flag isDeleted. Every table will have these two fields Id and IsDeleted.

Now we can define a trait, with all the available methods.

In the above code, we can see that that trait takes two types of parameters, T and E, which can be any sub types of BaseTable and BaseEntity respectively.

Now we can define a trait which defines the slick queries to do the above operations.

In the above BaseRepositoryQuery trait, in all the methods a filter with isDeleted is applied. This ensures that only the active records are fetched and updated.

Next step is to define a base repository which implements all the methods and executes the necessary queries.

That’s it! Just by extending your repository with BaseRepository, all the 6 methods are automatically available without writing any more code. If it is required to do anything more than what BaseRepository has to offer, your only need to override and provide your own implementation.

Let’s see how to create a repository for doing User operations.

We have a table User with fields (Id, UserName, Email, Password, IsDeleted). The Slick Table is defined as UserTable.

The User repository will look like this:

Now we can create an object of UserRepository and access all the 6 methods without writing any extra lines of code.

Assume that, you do not want to expose the password value when doing getById operation.

What if we need to implement some extra functionality which doesn’t fall under the pre-defined 6 methods?

BaseRepositoryQuery comes to the rescue here, as it allows you to extend and implement your own functionality.

For e.g.: Assume that we have 2 tables, User and Employee. We need to join these two tables to get the full User Details. It can be implemented as below

Now, what if we need to implement workflow to a few tables in the application?

We can create a more specific abstract Repository, which can be implemented by the tables requiring that functionality.

Any Repositories extending with WorkflowRepository will get the approve method, which can then be used to approve an operation.

That’s it, a repository pattern implementation in Slick is ready to be used.

 

The complete code is available at github. Please write to yadu.k@reactore.com with any feedback, suggestions and clarifications.

Share this post

Comments (12)

  • Josh Reply

    Hey Yadu,

    Nice post! This seems like a very clean way to use Slick with multiple tables.

    I was just wondering if you have a generic way to work with composite entities. For example, say I have a 3 table hierarchy where a Company can have many Departments and a Department has many Employees. Now, on CompanyRepository, I want my getById method to return a Company with all the nested entities inside. E.g. Company(name: String, departments: Seq[Department]) where department looks like: Department(name: String, employees: Seq[Employee]). However I’m not sure how to do this since getById needs to return the database row model. Perhaps the best way is to just implement a custom method getCompositeById in both DepartmentRepository and CompanyRepository and do some joins in there using the getByIdQuery? I feel like there should be a nicer and more generic way to do this though!

    Thanks,
    Josh

    August 17, 2016 at 2:10 pm
  • Yadu Krishnan Reply

    Hello Josh,
    Thanks for the appreciation :)

    I think what you want is like the full hierarchy loading like in Hibernate. When we switched from Java to Scala , this was probably the first thing we tried and found out that it is not directly possible with slick (since Slick is not an ORM also). So like you have mentioned in the comment, we are also writing additional custom method like getCompositeById to get the full hierarchy. Also, you can add caching for such commonly used tables, so that it will not create multiple database queries everytime those composite methods are accessed.

    August 18, 2016 at 9:31 am
  • Giovanni Reply

    Hello Josh,
    An even simpler solution I think is to define a view that fetches or denormalizes everything you need. Then have the slick-codegen generate a class for it and then you can do all the CRUDs so no need to deal with complex ORM graphs and state interactions.

    November 26, 2016 at 8:45 pm
  • Yadu Krishnan Reply

    @Giovanni, yes, it is a good idea for very commonly used tables. Only slight inconvenience is if any of the columns of the main tables are changed, we will need to update the view slick code as well. Except that, it is easy. Thanks for the suggestion. :)

    December 5, 2016 at 3:34 am
  • Mahdi (mah454) Reply

    Really , very very good tutorial for repository pattern ,
    Thank you men .

    December 17, 2016 at 11:40 pm
  • Piyush Reply

    Can we use slick code generation?

    March 10, 2017 at 8:14 am
  • Jonathan Reply

    Thanks very much for this post. I had been trying to do something like this for a while, but couldn’t get all the types to work out correctly. I’m grateful to you for sharing this with the community!

    While applying this pattern to my code, I tried to also make it generic with respect to database backend (so using JdbcProfile instead of PostgresProfile). The one place where this falls apart is in the BaseTable, which extends Table[E], which is a type that is determined based on which profile/driver is used. Since this is determined at runtime, I couldn’t figure out a way to do this — but perhaps you or one of your readers who has greater mastery of Scala’s “type magic” can figure out some way to do this (using a type member? or the type of an argument which is passed to the table?)

    In any case, thanks again for this valuable post!

    March 19, 2017 at 1:59 pm
  • Yadu Krishnan Reply

    Hi Piyush,
    Yes, You can use Slick code generator to generate the entities and slick tables for the database schema. Going one step ahead, you can even modify the code generator to generate your repository class using some templates(like free marker or velocity). So when you create a table and generate the slick entities, you will also get the Repository class with no additional work.

    March 20, 2017 at 6:42 am
  • Rajashree Reply

    Hi,

    Thanks for your post. I’m new to scala and slick. I’m still not clear on so many concepts in this.
    1. If we are using JPA(Hibernate) in java we will have default CRUDRepository which we can use directly. In one of the comments above, you have mentioned that “full hierarchy loading like in Hibernate”, Does it means we don’t have default Repository in slick?

    2. I also used Slick code generation, it generated the entity classes automatically but not the repository. If we use the code generator to generate repository class, does it not required to write this BaseEntity and BaseRepository?

    3. As per my understanding, BaseEntity/Repository acts like a Parent for all other entities. So whenever i want to implement CRUD operations, we can extend these things. Is that correct?

    May 22, 2017 at 8:51 pm
  • Richard Reply

    Hi yadu, thanks for your post

    How I can use this method:

    BaseRepositoryQuery–>
    def filterQuery[C C)(implicit wt: CanBeQueryCondition[C]) = {
    query.filter(expr).filter(_.isDeleted === false)
    }

    BaseRepository –>
    def filter[C C)(implicit wt: CanBeQueryCondition[C]) = {
    db.run(filterQuery(expr).result)
    }

    Can I would implement a filter with other column?, for example get all records where the value of column “active” is true.

    May 23, 2017 at 9:07 pm
  • Yadu Krishnan Reply

    Hello Richard,
    Sorry for the late reply.

    If you want to filter by the column “active” in BaseRepository filters, then you will need to add that field in BaseEntity and BaseTable.

    Also, you can extend the BaseRepository and create a level above it, say, ActiveBaseRepository[ActiveEntity,ActiveTable]. In this case, ActiveEntity and ActiveTable need to have the method “active”. Then, you can add the additional condition in your active repository filter, by overriding the filterQuery method and adding active=true

    May 30, 2017 at 10:41 am
  • Yadu Krishnan Reply

    Hello Rajashree,
    1. In Hibernate, you can load the entire hierarchy (with its children table records) directly, but in slick, you need to do that explicitly by using joins.
    2. Slick Code Generator will not generate the repository, we need to extend the slick code generator and write custom code to generate the repositories along with the tables and entities.
    3. Yes, exactly. Just by extending BaseRepository, you will be getting a few standard methods without you need to explicitly implement anything. Obviously, you have the flexibility to override and change the logic or restrict by throwing an exception from the overriden method.

    May 30, 2017 at 10:45 am

Leave a Reply

Your email address will not be published. Required fields are marked *