From a960f43cb6016aa0a2a17806cf66c7a8c4e89c02 Mon Sep 17 00:00:00 2001 From: nova Date: Sun, 17 May 2020 23:30:24 +0530 Subject: [PATCH] implemented table join --- app/controllers/HomeController.scala | 26 ++++++++++------- conf/routes | 1 + logs/application.log | 29 +++++++++---------- .../scala/com/example/models/Library.scala | 17 +++++++++-- .../com/example/services/LibraryService.scala | 2 ++ .../user/slick/dbios/SlickLibraryDbio.scala | 18 ++++++++---- .../slick/services/SlickLibraryService.scala | 11 +++++++ 7 files changed, 70 insertions(+), 34 deletions(-) diff --git a/app/controllers/HomeController.scala b/app/controllers/HomeController.scala index a312387..f965d80 100644 --- a/app/controllers/HomeController.scala +++ b/app/controllers/HomeController.scala @@ -11,23 +11,23 @@ import com.example.services.LibraryService import play.api.libs.json.Json @Singleton -class HomeController @Inject() (userDAO: UserDAO, carDAO: CarDAO, libraryService: LibraryService, cc: ControllerComponents) - (implicit ec: ExecutionContext) - extends AbstractController(cc) { +class HomeController @Inject() ( + userDAO: UserDAO, + carDAO: CarDAO, + libraryService: LibraryService, + cc: ControllerComponents +)(implicit ec: ExecutionContext) + extends AbstractController(cc) { def index = Action.async { implicit request => - userDAO.all.map { users => - Ok(views.html.index(users)) - } + userDAO.all.map { users => Ok(views.html.index(users)) } } def cars = Action.async { implicit request => - carDAO.all.map { cars => - Ok(views.html.cars(cars)) - } + carDAO.all.map { cars => Ok(views.html.cars(cars)) } } - def book = Action.async{ + def book = Action.async { // libraryService.findBookById(1).map(e => Ok(Json.toJson(e))) // libraryService.insertBookAndAuthor(Book("new book"), Author(2, "Some retard")) @@ -36,4 +36,10 @@ class HomeController @Inject() (userDAO: UserDAO, carDAO: CarDAO, libraryService } yield (Ok(Json.toJson(maybeBook))) } + def authors(bookId: Long) = Action.async { implicit request => + libraryService.getAuthorsForBook(bookId).map( t => { + Ok(Json.toJson(t)) + }) + } + } diff --git a/conf/routes b/conf/routes index 6b7520c..2f57c98 100644 --- a/conf/routes +++ b/conf/routes @@ -6,6 +6,7 @@ GET / controllers.HomeController.index GET /cars controllers.HomeController.cars GET /book controllers.HomeController.book +GET /authors/:bookId controllers.HomeController.authors(bookId: Long) # Map static resources from the /public folder to the /assets URL path GET /assets/*file controllers.Assets.versioned(path="/public", file: Asset) diff --git a/logs/application.log b/logs/application.log index 6715d85..4011d49 100644 --- a/logs/application.log +++ b/logs/application.log @@ -1,31 +1,28 @@ -2020-05-14 01:04:22,774 [INFO] from play.api.http.EnabledFilters in play-dev-mode-akka.actor.default-dispatcher-7 - Enabled Filters (see ): +2020-05-16 21:21:04,771 [INFO] from play.api.http.EnabledFilters in play-dev-mode-akka.actor.default-dispatcher-5 - Enabled Filters (see ): play.filters.csrf.CSRFFilter play.filters.headers.SecurityHeadersFilter play.filters.hosts.AllowedHostsFilter -2020-05-14 01:04:22,780 [INFO] from play.api.Play in play-dev-mode-akka.actor.default-dispatcher-7 - Application started (Dev) (no global state) -2020-05-14 01:04:41,915 [INFO] from play.api.http.EnabledFilters in play-dev-mode-akka.actor.default-dispatcher-7 - Enabled Filters (see ): +2020-05-16 21:21:04,777 [INFO] from play.api.Play in play-dev-mode-akka.actor.default-dispatcher-5 - Application started (Dev) (no global state) +2020-05-16 21:21:05,234 [DEBUG] from slick.jdbc.JdbcBackend.statement in myapp.database-1 - Preparing statement: select x2."ID", x2."NAME", x3.x4, x3.x5, x3.x6, x3.x7 from (select "ID" as x4, "AUTHOR_ID" as x6, "TITLE" as x5, "CREATED_AT" as x7 from "BOOKS" where "ID" = 2 limit 1) x3, "AUTHORS" x2 where x2."ID" = x3.x6 +2020-05-16 21:21:09,910 [DEBUG] from slick.jdbc.JdbcBackend.statement in myapp.database-2 - Preparing statement: select x2."ID", x2."NAME", x3.x4, x3.x5, x3.x6, x3.x7 from (select "ID" as x4, "AUTHOR_ID" as x6, "TITLE" as x5, "CREATED_AT" as x7 from "BOOKS" where "ID" = 1 limit 1) x3, "AUTHORS" x2 where x2."ID" = x3.x6 +2020-05-16 21:26:25,801 [INFO] from play.api.http.EnabledFilters in play-dev-mode-akka.actor.default-dispatcher-7 - Enabled Filters (see ): play.filters.csrf.CSRFFilter play.filters.headers.SecurityHeadersFilter play.filters.hosts.AllowedHostsFilter -2020-05-14 01:04:41,917 [INFO] from play.api.Play in play-dev-mode-akka.actor.default-dispatcher-7 - Application started (Dev) (no global state) -2020-05-14 01:04:46,364 [INFO] from play.api.http.EnabledFilters in play-dev-mode-akka.actor.default-dispatcher-7 - Enabled Filters (see ): +2020-05-16 21:26:25,804 [INFO] from play.api.Play in play-dev-mode-akka.actor.default-dispatcher-7 - Application started (Dev) (no global state) +2020-05-16 21:26:25,894 [DEBUG] from slick.jdbc.JdbcBackend.statement in myapp.database-1 - Preparing statement: select x2."ID", x2."NAME", x3."ID", x3."TITLE", x3."AUTHOR_ID", x3."CREATED_AT" from "AUTHORS" x2, "BOOKS" x3 where (x3."ID" = 1) and (x2."ID" = x3."AUTHOR_ID") +2020-05-16 21:29:57,361 [INFO] from play.api.internal.libs.concurrent.CoordinatedShutdownSupport in pool-14-thread-4 - Starting synchronous coordinated shutdown with ServerStoppedReason reason and 35000 milliseconds timeout +2020-05-16 21:29:57,362 [INFO] from play.core.server.AkkaHttpServer in pool-14-thread-4 - Stopping Akka HTTP server... +2020-05-16 21:29:57,363 [INFO] from play.core.server.AkkaHttpServer in play-dev-mode-akka.actor.internal-dispatcher-3 - Terminating server binding for /0:0:0:0:0:0:0:0:8080 +2020-05-16 21:29:59,781 [INFO] from play.api.http.EnabledFilters in play-dev-mode-akka.actor.internal-dispatcher-17 - Enabled Filters (see ): play.filters.csrf.CSRFFilter play.filters.headers.SecurityHeadersFilter play.filters.hosts.AllowedHostsFilter -2020-05-14 01:04:46,366 [INFO] from play.api.Play in play-dev-mode-akka.actor.default-dispatcher-7 - Application started (Dev) (no global state) -2020-05-14 10:15:22,298 [INFO] from play.core.server.AkkaHttpServer in play-dev-mode-shutdown-hook-1 - Stopping Akka HTTP server... -2020-05-14 10:15:22,300 [INFO] from play.core.server.AkkaHttpServer in play-dev-mode-akka.actor.internal-dispatcher-5 - Terminating server binding for /0:0:0:0:0:0:0:0:8080 -2020-05-14 10:15:32,165 [INFO] from play.api.http.EnabledFilters in play-dev-mode-akka.actor.internal-dispatcher-15 - Enabled Filters (see ): - - play.filters.csrf.CSRFFilter - play.filters.headers.SecurityHeadersFilter - play.filters.hosts.AllowedHostsFilter - -2020-05-14 10:15:32,176 [INFO] from play.api.Play in play-dev-mode-akka.actor.internal-dispatcher-15 - Application started (Dev) (no global state) -2020-05-14 10:15:32,221 [INFO] from play.core.server.AkkaHttpServer in play-dev-mode-akka.actor.internal-dispatcher-18 - Running provided shutdown stop hooks +2020-05-16 21:29:59,783 [INFO] from play.api.Play in play-dev-mode-akka.actor.internal-dispatcher-17 - Application started (Dev) (no global state) +2020-05-16 21:29:59,810 [INFO] from play.core.server.AkkaHttpServer in play-dev-mode-akka.actor.internal-dispatcher-19 - Running provided shutdown stop hooks diff --git a/modules/api/src/main/scala/com/example/models/Library.scala b/modules/api/src/main/scala/com/example/models/Library.scala index 7b2a7c1..28f69ca 100644 --- a/modules/api/src/main/scala/com/example/models/Library.scala +++ b/modules/api/src/main/scala/com/example/models/Library.scala @@ -3,12 +3,23 @@ package com.example.models import play.api.libs.json.Json import java.time.Instant -final case class Book(id: Long, title: String, authorId: Long, createdAt: Instant) +final case class Book( + id: Long, + title: String, + authorId: Long, + createdAt: Instant +) final case class NewBook(title: String, authorId: Long) final case class BookDTO(title: String, authorId: Long, createdAt: Instant) final case class Author(id: Long, name: String) final case class NewAuthor(name: String) object Book { - implicit val bookJsonWrite = Json.format[Book] -} \ No newline at end of file + def tupled = (Book.apply _).tupled + implicit val bookJsonFormat = Json.format[Book] +} + +object Author { + def tupled = (Author.apply _).tupled + implicit val authorsJsonFormat = Json.format[Author] +} diff --git a/modules/api/src/main/scala/com/example/services/LibraryService.scala b/modules/api/src/main/scala/com/example/services/LibraryService.scala index b0e2eda..d93e8e8 100644 --- a/modules/api/src/main/scala/com/example/services/LibraryService.scala +++ b/modules/api/src/main/scala/com/example/services/LibraryService.scala @@ -23,4 +23,6 @@ trait LibraryService { // Insert a book and an author composing two DBIOs in a transaction def insertBookAndAuthor(book: NewBook, author: NewAuthor): Future[(Long, Long)] + + def getAuthorsForBook(id: Long): Future[Seq[(Author, Book)]] } diff --git a/modules/slick/src/main/scala/com/example/user/slick/dbios/SlickLibraryDbio.scala b/modules/slick/src/main/scala/com/example/user/slick/dbios/SlickLibraryDbio.scala index 83d055f..7a684be 100644 --- a/modules/slick/src/main/scala/com/example/user/slick/dbios/SlickLibraryDbio.scala +++ b/modules/slick/src/main/scala/com/example/user/slick/dbios/SlickLibraryDbio.scala @@ -36,6 +36,10 @@ class SlickLibraryDbio extends Tables { def insertAuthor2(author: NewAuthor): DBIO[Long] = Query.writeAuthors2 += author + def getAuthorsForBook(bookId: Long): DBIO[Seq[(AuthorsRow, BooksRow)]] = { + Query.authorOfBook(bookId).result + } + def authorToRow(author: Author) = author.transformInto[AuthorsRow] def bookToRow(book: Book) = book.transformInto[BooksRow] def authorsRowToAuthor(author: AuthorsRow) = author.transformInto[Author] @@ -76,16 +80,20 @@ class SlickLibraryDbio extends Tables { lazy val authorOfBook = (bookId: Long) => for { - (authors, books) <- Authors join Books on (_.id === _.authorId) filter { + (author, book) <- Authors join + Books on (_.id === _.authorId) filter { case (authors, books) => books.id === bookId } - } yield (authors, books) + } yield (author, book) lazy val authorOfBook2 = (bookId: Long) => for { - authorId <- Books.filter(_.id === bookId).take(1).map(_.authorId) - authors <- Authors filter (_.id === authorId) - } yield (authors.name) + (authorId, book) <- Books + .filter(_.id === bookId) + .take(1) + .map(b => (b.authorId, b)) + author <- Authors filter (_.id === authorId) + } yield (author, book) // lazy val authorOfBook3 = (bookId: Long) => // for { diff --git a/modules/slick/src/main/scala/com/example/user/slick/services/SlickLibraryService.scala b/modules/slick/src/main/scala/com/example/user/slick/services/SlickLibraryService.scala index 014c664..e7a62d4 100644 --- a/modules/slick/src/main/scala/com/example/user/slick/services/SlickLibraryService.scala +++ b/modules/slick/src/main/scala/com/example/user/slick/services/SlickLibraryService.scala @@ -16,6 +16,17 @@ class SlickLibraryService @Inject() ( libraryDbio: SlickLibraryDbio )(implicit ec: ExecutionContext) extends LibraryService { + + override def getAuthorsForBook(id: Long): Future[Seq[(Author, Book)]] = { + db.run{ + libraryDbio.getAuthorsForBook(id).map(_.map { + case (x, y) => { + ( libraryDbio.authorsRowToAuthor(x), libraryDbio.booksRowToBooks(y)) + } + }) + } + } + import libraryDbio.profile.api._ // Simple function that returns a book