Как внедрить play.api.db.slick.Config.driver.simple.Session внутрь удобного компонента DAO

Я использую шаблон торта для внедрения зависимостей между компонентами в приложении play 2.2.1. Приложение состоит из игровых контроллеров, и мы используем пользовательский ActionBuilder для открытия нашего сеанса БД. В настоящее время мы передаем этот сеанс БД обратно на уровень нашей модели через уровни контроллера и DAO в качестве неявного аргумента. (ActionBuilder -> Контроллер -> DAO -> Модель Slick)

Я использую play-slick для плавной интеграции и пытаюсь использовать подход DAO для инкапсуляции доступа к нашим гладким моделям. Наши DAO имеют несколько определений функций, таких как findById(id: Int)(implicit s: Session): Option[Entity]. Я хотел бы избежать этого неявного параметра сеанса в каждом отдельном определении функции, внедрив компонент, извлекающий DBSession. Этот компонент будет вызываться внутри функциональных блоков DAO каждый раз для получения текущего сеанса БД запроса.

Исходя из мира Java и Spring, я точно не знаю, как этого добиться, учитывая, что я, вероятно, не могу полагаться на какой-либо прокси-сервер с областью действия ThreadLocal.

Есть идеи, как я смогу этого добиться? Это хорошая или плохая идея?


person srirachapills    schedule 29.07.2014    source источник


Ответы (2)


Вы можете поместить все свои методы в класс, который принимает неявный сеанс в качестве аргумента, а затем вы всегда сначала создаете экземпляр класса, а затем вызываете метод. Пример здесь: http://slick.typesafe.com/doc/2.0.2/connection.html#passing-sessions-around

person cvogt    schedule 29.07.2014
comment
Это не самый элегантный IMO, но я думаю, что это мое последнее средство, если мы не можем полагаться на какое-то краткосрочное хранилище для сеанса БД. - person srirachapills; 29.07.2014
comment
Вы используете класс, чтобы в основном реализовать частичное приложение для множества методов одновременно. Существует также dynamicSession, который является своего рода краткосрочным хранилищем для сеанса базы данных, но он гораздо менее элегантен и обычно не рекомендуется. Элегантность исходит не обязательно от красоты синтаксиса, а от надежности и простоты использования концепции. - person cvogt; 30.07.2014
comment
Монада Action, появившаяся в Slick 2.2, может быть более элегантным решением, позволяющим составлять не только запросы, но и смесь запросов и обычного кода Scala без явного раскрытия сеанса. - person cvogt; 30.07.2014

Если вы можете получить сеанс БД как функцию запроса, вы можете предоставить неявное преобразование для преобразования запроса => DBSession.

Так:

implicit def request2DBSession(request: Request[T]): DBSession = ???

Внутри которого вы можете выполнить поиск DBSession.

РЕДАКТИРОВАТЬ:

Еще лучше вы можете использовать композицию действий для внедрения сеанса с каждым запросом:

trait BaseController extends Controller {
  def DBAction(f: (request[_]) => DBSession => Result) = {
    Action { request =>
      val dbSession = ??? // Lookup DBSession
      f(request)(dbSession)
    }
  }  
}

object Controller extends BaseController {
  def lookupUser = DBAction { implicit request => implicit dbSession =>
    ??? // DBSession in Implicit Scope (free to use slick calls)
  }
}

Это было бы немного чище, на мой взгляд.

person Bryan    schedule 29.07.2014
comment
Мой вопрос в том, как мы можем избежать этого! Я хочу смешать компонент SessionLocator с компонентами DAO, которые смогут предоставить мне этот сеанс. В противном случае я должен объявить этот параметр везде в своих чертах DAO! - person srirachapills; 29.07.2014
comment
Ах извините! Похоже, я неправильно понял ваш вопрос. Вы могли бы потенциально обернуть сеанс внутри объекта Dao и создать его экземпляр внутри действия. Затем построитель действий может передать дао встроенной функции вместо сеанса. Таким образом, код контроллера никогда не должен был бы видеть Session. Вы также можете сделать это, введя компонент извлечения dao вместо компонента извлечения сеанса, о котором вы думали. Помимо чего-то подобного, любое решение, которое я могу придумать, было бы хуже, чем исходная проблема с использованием имплицитов. - person Bryan; 31.07.2014