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.properties.url="jdbc:postgresql://localhost:5432/CrudOpe
ration?currentSchema=public"
slick.dbs.default.profile="slick.jdbc.PostgresProfile$"
slick.dbs.default.db.url="jdbc:postgresql://localhost:5432/CrudOperation"
slick.dbs.default.db.username="postgres"
slick.dbs.default.db.password="postgres"
slick.dbs.default.db.connectionTestQuery = "SELECT 1"
play.evolutions.autoApply=true
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(
email:Option[String],
name:String
)
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] =
(
email.?,
name) <>((User.apply _).tupled, User.unapply)
}
User table query
private val users = TableQuery[UserTableDef]
def getAllUsers: Future[Seq[User]] ={
dbConfig.db.run(users.result)
}
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] ={
dbConfig.db.run(users.filter(_.email===Email).delete)
}
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] =>
Ok(views.html.index())
}
getAllUser method which is used to call user table query from the repository
def getAllUsers: Action[AnyContent] =Action.async{ implicit request =>
userRepository.getAllUsers.map{user=>
Ok(views.html.user(user))
}
}
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),
name,
)
userRepository.getUserByEmail(email).flatMap {
case Some(_) => Future.successful(Ok("User already exist!"))
case None => userRepository.addUser(user).map { _ =>
Ok(views.html.index())
}
}
}
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=>
userRepository.deleteUserByEmail(email).map{
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)
userRepository.updateUserNameByEmail(email,user).map{
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
controllers.HomeController.addUser(email:String,name:String)
GET /updateUserNameByEmail
controllers.HomeController.updateUserNameByEmail(email:String,name:String)
GET /allUsers controllers.HomeController.getAllUsers
GET /deleteUserByUserId
controllers.HomeController.deleteUserByEmail(email:String)
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




Template link:- https://techhub.knoldus.com/dashboard/search-result/crud/6294ddd8ea09b33f796287ab
Conclusion
Through this blog, You will get the Solution for CRUD operations by using Scala, Play framework. and Postgres slick.