【问题标题】:Scala + Play Framework + Slick + Akka - DB Access from Akka ActorScala + Play Framework + Slick + Akka - 来自 Akka Actor 的数据库访问
【发布时间】:2016-11-25 11:43:32
【问题描述】:

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

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

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

Tcp 服务器是接收到消息的 Actor,需要将消息推送到 DB Actor 上

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

根据 Play Framework 规范,DB Actor 以这种方式初始化

    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没有被构造

    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)

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

此时的问题是,让参与者访问数据库或至少是控制器是否有意义?如果做不到,有什么办法?

【问题讨论】:

    标签: scala playframework akka slick


    【解决方案1】:

    你需要的是一个注入的actor。完整的描述可以在播放文档 (https://www.playframework.com/documentation/2.5.x/ScalaAkka#Dependency-injecting-actors) 中找到,但这里是它的要点:

    你像这样定义actor绑定:

    bindActor[DBActor]("db-actor")
    

    然后像这样在控制器中注入actor:

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

    另外,您应该尽可能避免使用Await.result。在您的场景中,这可能很容易替换为:

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

    请注意,发送者 ref 之前已存储,因为它在 map 中不再有效(请参阅 sender() 方法的 scaladoc)。

    【讨论】:

    • 好的,它确实有效,我必须以这种方式注册应用程序的所有参与者。谢谢
    猜你喜欢
    • 1970-01-01
    • 2015-01-06
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 2015-06-11
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    相关资源
    最近更新 更多