Hands-on CRUD operation with Scala-Play

Reading Time: 3 minutes

Hi folks in this blog, we perform CRUD(Create, Read, Update, Delete) operations using Scala, Play framework, and Postgres Slick

Project Setup

We must install the SBT command-line tool (at least JDK 8). This Project uses SBT version 1.6.2 to install Play Framework version 2.8.1 and the Postgres database.

Now you need to download the hello word template in play scala. Run ‘ sbt new playframework/play-scala-seed.g8’ on your terminal and it asks for some details

name [play-scala-seed]:
organization [com.example]:
play_version [2.8.18]:
scala_version [2.13.10]:

after that run ‘sbt run’ command. now we are moving to implement crud operation.

Step 1:

First, we need to add some dependencies in the build.sbt file.

libraryDependencies ++= Seq(

  "org.scalatestplus.play" %% "scalatestplus-play" % "5.0.0" % Test,

  "com.typesafe.play"    %% "play-slick"            % "5.0.0",

  "org.postgresql"        % "postgresql"            % "42.3.1",

  "com.typesafe.play"    %% "play-slick-evolutions" % "5.0.0",

  "com.github.jwt-scala" %% "jwt-play-json"         % "9.0.3",

  "com.github.tminglei"  %% "slick-pg"              % "0.20.2",

  "com.github.tminglei"  %% "slick-pg_play-json"    % "0.20.2"

Step 2:

Now we connect the Postgres database with our application so add configuration in the conf package application.conf file

slick.dbs.default.db.properties.driver = "org.postgresql.Driver"







slick.dbs.default.db.connectionTestQuery = "SELECT 1"


for creating a user table to add a 1.sql file in conf/evolutions/default/

create table users (
    email_id varchar(50) primary key,

    name varchar(100) not null

Step 3:

Great, we connected the application with the database. now we will create a model which handles the user data under the models package

package models

import play.api.libs.json.{ Json, OFormat }

case class User(




object  User {

  implicit val userFormat: OFormat[User] = Json.format[User]


Step 4:

Creating a Repository package and under the package, we will create a user repository file to access the data from the user table

User table by using the Slick

class UserTableDef(tag: Tag) extends Table[User](tag, "users") {

  def email: Rep[String] = column[String]("email_id",O.PrimaryKey)
  def name: Rep[String] = column[String]("name")

  override def * : ProvenShape[User] =


      name) <>((User.apply _).tupled, User.unapply)


User table query

private val users = TableQuery[UserTableDef]

def getAllUsers: Future[Seq[User]] ={
def getUserByEmail(email:String): Future[Option[User]] ={
      dbConfig.db.run(users.filter(_.email === email).result.headOption)

def addUser(user: User): Future[Int] ={
      dbConfig.db.run(users += user)

def deleteUserByEmail(Email:String): Future[Int] ={
def updateUserNameByEmail(email:String,user:User): Future[Int] ={

   dbConfig.db.run(users.filter(_.email === email).update(user))


Step 5:

Creating a Home controller file under the controllers package that works as a communicator between the model and the view

index method which use to redirect the home page

def index(): Action[AnyContent] = Action { implicit request:            
    Request[AnyContent] =>



getAllUser method which is used to call user table query from the repository

def getAllUsers: Action[AnyContent] =Action.async{ implicit request =>





addUser method which is used to create a new user and call a user table query from the repository

def addUser(email:String,name:String): Action[AnyContent] = Action.async{

    implicit request =>

      val user = User(

       Some( email),



      userRepository.getUserByEmail(email).flatMap {

        case Some(_) => Future.successful(Ok("User already exist!"))

        case None    => userRepository.addUser(user).map { _ =>




deleteUserByEmail method which is used to delete the user and call the user table query from the repository

def deleteUserByEmail(email:String): Action[AnyContent] = Action.async{
   implicit request=>


        case 1 => Ok(views.html.deleteUser("Deleted"))

        case 0 => Ok(views.html.deleteUser(""))


updateUserByEmail method which is used to update the user and call the user table query from the repository.

def updateUserNameByEmail(email:String,name:String): Action[AnyContent]  

  = Action.async{
     implicit request=>
        val user =User(Some(email),name)
          case 1=>Ok(views.html.updateUser("Updated"))
          case 0=>Ok(views.html.updateUser(""))

Step 5:

Now we adding some routes under the conf/route package

GET     /                             controllers.HomeController.index()

GET     /addUser                      


GET     /updateUserNameByEmail        


GET     /allUsers                     controllers.HomeController.getAllUsers

GET     /deleteUserByUserId           


Step 6:

Done with the coding part. now we compile the project using SBT commands. run this command on your terminal

$ sbt compile run

Open your favorite browser and enter this URL http://localhost:9000

Enter the details and press ADD button after that press the All Users button
You will see all users on the next page. if you want to try the Update and Delete operation just press the button and enter the details

Template link:- https://techhub.knoldus.com/dashboard/search-result/crud/6294ddd8ea09b33f796287ab


Through this blog, You will get the Solution for CRUD operations by using Scala, Play framework. and Postgres slick.

Written by 

Vineet Chauhan is a Software Consultant at Knoldus Inc. His practice area is Scala. He is a good team worker. He is always ready to face any challenging task.