使用Slick在Akka的Actor中插入记录的最佳方法是什么?

时间:2016-04-23 23:59:10

标签: postgresql scala akka slick actor

我正在尝试使用DB actor将记录插入数据库。我有数百万的记录。但是在操作之后,数据库只有十条记录。我知道数据库连接是一个状态,我认为这种情况有问题。这是我的代码代表。

class DBActor extends Actor with DBConfig {
  override def receive: Receive = {
    case Message(id, title) =>
      db.run(products += Product(id, title))
  }
}

数据库是关系数据库,'products'是TableQuery,DBConfig有数据库连接和会话。在保证下插入记录的最佳方法是什么。

1 个答案:

答案 0 :(得分:3)

使用批次而不是逐个来保留记录。 db.run()方法是异步的,所以它返回将来的立即执行,稍后在不同的线程上执行,因此除了方法调用(db.run)之外,Actor没有做任何事情。你应该使用resister回调(onFailure)关于db.run()方法的结果,以便您可以查看是否发生任何故障。参见示例(它不是编译代码):

case object Insert

case object Flush

class DBActor extends Actor with DBConfig {


   implicit val dispatcher = context.dispatcher

   val bulkLimit:Int = 1000

   val flushTime:Int = 10

  var documents = List.empty[Product]

 /***
  * Start automatic flushing when actor start
  */
  context.system.scheduler.scheduleOnce(flushTime second, self, Flush)

 def receive:Receive={

case document: Document =>
  documents =documents :+ document
  log.info(s"DBActor received document [total count ${documents.length}]")
  if (documents.length >= bulkLimit) self ! Insert

case Insert =>
  if (documents.length > 0) {
    val batch = documents.take(bulkLimit)
    db.run(products ++= batch).onFailure { case ex: Exception => log.error("Getting error on persisting  data", ex) }
    documents = documents.drop(bulkLimit)
  }

case Flush =>
  if (documents.length > 0) self ! Insert

  context.system.scheduler.scheduleOnce(flushTime second, self, Flush)
}

}