简体   繁体   English

为Scala播放:Scala对象为DAO

[英]Play for Scala: Scala object as DAO

I am used to frameworks like Ruby on Rails or Laravel in PHP where I have models like User and when I want to make a query to the model (for example, to get all the users in the database) I do something like User::all() . 我已经习惯了Ruby on Rails或Laravel这样的框架,我有像User这样的模型,当我想对模型进行查询时(例如,为了获取数据库中的所有用户),我做了像User::all()

I'm new to Play for Scala and Slick, and all the projects and documentation I've already seen use a DAO for accessing the database through a model. 我是Play for Scala和Slick的新手,我已经看过的所有项目和文档都使用DAO通过模型访问数据库。 I've thought that a Scala object is what I need (or at least I am accustomed to) so I don't need to inject DAO classes everywhere. 我认为Scala object是我需要的(或者至少我已经习惯了)所以我不需要在任何地方注入DAO类。

With a DAO I do something like this: 使用DAO我做这样的事情:

class Application @Inject()(adminDAO: AdminDAO) extends Controller {
  def index = Action.async {
    adminDAO.all() map { case admins =>
      Ok(Json.toJson(admins))
    }
  }
}

And with an object (and no idea) I expect to do something like this: 有了一个对象(并且不知道)我希望做这样的事情:

class Application extends Controller {
  def index = Action.async {
    Admin.all() map { case admins =>
      Ok(Json.toJson(admins))
    }
  }
}

Trying to implement the "DAO" object I have found almost impossible to to inject the Play Application context without using Play.current which is deprecated. 尝试实现“DAO” object我发现几乎不可能在不使用不推荐的Play.current情况下注入Play Application上下文。 That kind of deprecation and the absence of a way of injecting the context (or at least I haven't found it) sounds strange to me. 这种贬低和缺乏注入上下文的方式(或者至少我没有发现它)对我来说听起来很奇怪。 I'm starting to think that I'm thinking it the wrong way. 我开始认为我认为这是错误的方式。 Is it really a good idea to use a Scala object as DAO? 将Scala object用作DAO真的是个好主意吗?

It comes down to dependency injection (DI) vs hardcoding dependencies. 它归结为依赖注入(DI)与硬编码依赖关系。 Your first example makes use of DI, your second one hardcodes the dependency against the Admin DAO. 你的第一个例子使用了DI,你的第二个例子硬编码了对Admin DAO的依赖。 The Play team has decided to go with DI in recent releases in an effort to remove global state (for a discussion why global state is a bad thing see here for example ): Play团队决定在最近的版本中使用DI来努力消除全局状态(例如,为什么全球状态是一件坏事,请参阅此处 ):

Play now, out of the box, uses dependency injection provided by Guice. 现在玩,开箱即用,使用Guice提供的依赖注入。 This is part of a long term strategy to remove global state out of Play, which we hope to complete in the Play 3.0 release. 这是消除Play全球状态的长期策略的一部分,我们希望在Play 3.0版本中完成。

Source 资源

Hence the right way when it comes to Play is your example 1, using an object and hence a hardcoded dependency is indeed inadvisable purely based on the fact that you work against play (however DI has many advantages too). 因此,当谈到Play时,正确的方法是你的例子1,使用一个对象,因此硬编码的依赖确实是不可取的,纯粹基于你对抗游戏的事实(但DI也有许多优点)。

I'm not well versed in Ruby, but as far as I know DI with frameworks (eg Guice) as it comes in Java/Scala isn't needed because Ruby has certain language features to solve the problem differently, which might be why you are wondering about the whole point of it all. 我不熟悉Ruby,但据我所知,DI与框架(例如Guice)不同,因为它有Java / Scala,因为Ruby有某些语言功能可以不同地解决问题,这可能就是为什么你我们想知道这一切的重点。 I recommend you read a bit about dependency injection in a Java/Scala context, that should clear up how it works, what problems it solves and what the (dis)advantages are (and since you know Ruby, why it isn't needed in Ruby in the same way). 我建议你在Java / Scala上下文中阅读一些关于依赖注入的内容,它应该清楚它是如何工作的,它解决了什么问题以及(dis)的优点(因为你知道Ruby,为什么不需要它) Ruby以同样的方式)。

Trying to implement the "DAO" object I have found almost impossible to to inject the Play Application context without using Play.current which is deprecated. 尝试实现“DAO”对象我发现几乎不可能在不使用不推荐的Play.current的情况下注入Play应用程序上下文。 That kind of deprecation and the absence of a way of injecting the context (or at least I haven't found it) sounds strange to me. 这种贬低和缺乏注入上下文的方式(或者至少我没有发现它)对我来说听起来很奇怪。

You should be able to simply inject the application context into your DAO, eg like this: 您应该能够简单地将应用程序上下文注入DAO,例如:

class AdminDao @Inject()(val application : Application) { 

and then you have the application available. 然后你有应用程序可用。 This is the equivalent to the deprecated 这相当于弃用

val application = Play.current

In both cases you capture the running Application . 在这两种情况下,您都捕获正在运行的Application The depencency injection framework behind it all makes sure that dependencies are resolved recursively, ie when you depend on your DAO in a controller it notes that the DAO itself depends on the application. 它背后的依赖注入框架都确保依赖性以递归方式解析,即当您依赖于控制器中的DAO时,它会注意到DAO本身依赖于应用程序。 It resolves the application, injects it into a new DAO instance and finally injects that into your controller. 它解析应用程序,将其注入新的DAO实例,最后将其注入您的控制器。

And last but not least many ways lead to rome as usual: Maybe ActiveSlick is something that you find useful (disclaimer: Haven't tried it myself). 最后但并非最不重要的是,许多方式像往常一样导致罗马:也许ActiveSlick是你觉得有用的东西(免责声明:我自己没试过)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM