Scala + Play框架+ Slick + Akka-Akka Actor的数据库访问 [英] Scala + Play Framework + Slick + Akka - DB Access from Akka Actor

查看:78
本文介绍了Scala + Play框架+ Slick + Akka-Akka Actor的数据库访问的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在接收TCP特定消息时,我需要查询我的数据库.为此,我创建了一个称为DBActor的Actor,并将其加载到Application.scala文件

At the receival of a TCP specific message, i need to query my DB. For that, i created an Actor that is called DBActor and it's loaded in Application.scala file

    class Application @Inject() (system: ActorSystem) extends Controller {

      val tcpServer = system.actorOf(Props[TCPServer], "tcpserver")
      val dbActor = system.actorOf(Props[DBActor], "dbActor")
    }

Tcp服务器是收到消息的参与者,需要将该消息推送到DB Actor上

Tcp server is the actor that received the message and need to push it on DB Actor with that

      val handler = context.actorSelection("/dbActor")

根据Play框架规范,DB actor以此方式进行了初始化

DB actor is so initialized in this way, according to Play Framework specifications

    object DBActor {
      def props() =
        Props(classOf[DBActor])
    }


    class DBActor @Inject() (protected val dbConfigProvider:
         DatabaseConfigProvider) extends Actor 
         with HasDatabaseConfigProvider[JdbcProfile] 
         with ActorLogging 
         with TableComponent {

      import akka.io.Tcp._
      import driver.api._

      val table = TableQuery[Table]

      def receive: Receive = {
        case GetConfig(id) => {
          sender ! Await.result(db.run(table.filter(_.id=== id).result.headOption), 
                Duration.Inf)
            .map { x => x.config }
        }
      }
    }

目前,由于错误,actor尚未构建

At the moment, actor is not constructed due to the error

    Error injecting constructor, java.lang.IllegalArgumentException: 
      no matching constructor found on class tcp.DBActor for arguments []
      at controllers.Application.<init>(Application.scala:17)
      at controllers.Application.class(Application.scala:17)

因此,我需要一种将DB配置注入DBactor中以查询数据库或替代方法的方法.在此之前,我评估过注入DAO或将所需的DAO转换为actor都失败了.

So i need a way to inject the db configuration in the DBactor for querying the database or an alternative. I evaluated before that to inject a DAO or transforming the DAO I needed into an actor, both failed.

在这一点上的问题是,赋予演员访问数据库或至少访问控制器是否有意义?如果无法完成,还有哪些选择?

Question at this point is, does it make any sense giving an actor the access to the db or, at least, a controller? If can't be done, what are the alternatives?

推荐答案

您需要的是注入的actor.完整说明可在播放文档中找到( https: //www.playframework.com/documentation/2.5.x/ScalaAkka#Dependency-injecting-actors ),但这是要点:

What you need is an injected actor. The full description can be found here in the play documentation (https://www.playframework.com/documentation/2.5.x/ScalaAkka#Dependency-injecting-actors), but here's the gist of it:

您可以像这样定义actor绑定:

You define the actor binding like so:

bindActor[DBActor]("db-actor")

然后将actor注入到控制器中,如下所示:

And inject the actor in the controller like so:

class Application @Inject() (@Named("db-actor") dbActor: ActorRef) extends Controller {

换句话说,您应尽可能避免使用Await.result.在您的情况下,可以很容易地将其替换为:

On a different note, you should avoid Await.result whenever possible. In your scenario, this could probably easily be replaced with:

val senderRef = sender()
db.run(table.filter(_.id=== id).result.headOption)
  .map(res => senderRef ! res.config)

请注意,发件人ref之前已存储,因为它在map内部不再有效(请参见sender()方法的scaladoc).

Note that the sender ref is stored before, because it is no longer valid inside the map (see scaladoc of the sender() method).

这篇关于Scala + Play框架+ Slick + Akka-Akka Actor的数据库访问的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆