есть несколько вопросов, которые вылезли практически сразу, не успев донести и первый мелкий проект до продакшена. может, кто-то поможет победить, а то скала нравится очень, но пока что есть боль.
вопросы на примере кода
package dao
import javax.inject.Inject
import model.FullKeyword
import play.api.db.slick.DatabaseConfigProvider
import slick.jdbc.JdbcProfile
import scala.concurrent.ExecutionContext
class DAO @Inject() (dbConfigProvider: DatabaseConfigProvider)(implicit ec: ExecutionContext) {
private val dbConfig = dbConfigProvider.get[JdbcProfile]
import dbConfig._
import profile.api._
import tables._
def keywordById(id: Int) = db.run(keywords.filter(_.id === id).result).map(_.headOption)
def linksByKeywordId(keywordId: Int) = db.run(links.filter(_.keywordId === keywordId).result)
def imagesByKeywordId(keywordId: Int) = db.run(images.filter(_.keywordId === keywordId).result)
def relatedByKeywordId(keywordId: Int) = db.run(relatedQueries.filter(_.keywordId === keywordId).result)
def fullKeywordById(id: Int) = keywordById(id).map(_.map(keyword => {
for {
links <- linksByKeywordId(keyword.id)
related <- relatedByKeywordId(keyword.id)
images <- imagesByKeywordId(keyword.id)
} yield(FullKeyword(keyword = keyword,links = links,related = related,images = images))
}))
def countKeywords = db.run(keywords.size.result)
def keywordsNPart(n: Int,size: Int) = {
val fromId = n*size + 1
val toId = fromId + size
db.run(keywords.filter(e => e.id >= fromId && e.id < toId).sortBy(_.id.asc).result)
}
}
-
class DAO @Inject() (dbConfigProvider: DatabaseConfigProvider)(implicit ec: ExecutionContext) { private val dbConfig = dbConfigProvider.get[JdbcProfile]
использую slick 3.2 и это в нем уже диприкейтед. свежее экзамплов не нашел. собственно, как же сейчас?
-
везде в экзамплах делают именно это: импортируют провайдер и вызывают у него .get[A]. я вижу здесь только противоречие IoC и ничего больше. в чем я не прав? не используется ни инициализация по требованию, никуда ниже компонентом провайдер тоже не передается, ну то есть нет в чем разумном их заподозрить.
private val dbConfig = dbConfigProvider.get[JdbcProfile]
-
сам апи выглядит довольно низкоуровневым:
- везде пишешь эти db.run(query.filter(...).result), когда кажется нормальным что-то вроде query.filter(...).execute
- импорт implicit из переменной dbConfig.profle.api._ `===` выглядит как копипаста, если писать много всяких DAO. это вообще нормально? выглядит как какой-то странный полиморфизм
-
вообще почти одинаковых три метода. как это сократить до def itemByKeywordId(item: TableQuery[?],keywordId: Int) и что за типы тут будут и где интерфейс для keywordId заимплиментить?
def linksByKeywordId(keywordId: Int) = db.run(links.filter(_.keywordId === keywordId).result) def imagesByKeywordId(keywordId: Int) = db.run(images.filter(_.keywordId === keywordId).result) def relatedByKeywordId(keywordId: Int) = db.run(relatedQueries.filter(_.keywordId === keywordId).result)
-
тут вообще похоже на какой-то жаваскрипт получается. Future[Option[Future]] как сократить до Option[Future] ?
def fullKeywordById(id: Int) = keywordById(id).map(_.map(keyword => { for { links <- linksByKeywordId(keyword.id) related <- relatedByKeywordId(keyword.id) images <- imagesByKeywordId(keyword.id) } yield(FullKeyword(keyword = keyword,links = links,related = related,images = images)) }))
и, как я понимаю, именно здесь и понадобился нам ExecutionContext, и мы завернули в кучу Future код, который оказался блокирующим. или зачем тут ExecutionContext ?
да и в целом класс получился как неймспес для методов. ООП тут точно нет. где тогда ФП и, конечно, где от него кайф?