Как правильно управлять гладкими соединениями с базой данных? - PullRequest
0 голосов
/ 18 октября 2018

AFAIK Слик способ доступа к базе данных состоит в том, чтобы создать неявный экземпляр session (по одному на приложение) и передать его везде в приложении через параметры implicit, что сеанс предоставит доступ к базе данных через значение db имы можем выполнить наши запросы, используя session.db.run.

Проблема для меня заключается в том, как я могу узнать, сколько соединений (реальных, не концептуальных) действительно создает экземпляр?

Яспрашивая об этом, потому что у меня было исключение из SQLite:

java.sql.SQLException: [SQLITE_BUSY]  The database file is locked (database is locked)
    at org.sqlite.DB.newSQLException(DB.java:383)
    at org.sqlite.DB.newSQLException(DB.java:387)
    at org.sqlite.DB.throwex(DB.java:374)
    at org.sqlite.NativeDB.prepare(Native Method)
    at org.sqlite.DB.prepare(DB.java:123)
    at org.sqlite.PrepStmt.<init>(PrepStmt.java:42)
    at org.sqlite.Conn.prepareStatement(Conn.java:404)
    at org.sqlite.Conn.prepareStatement(Conn.java:399)
    at org.sqlite.Conn.prepareStatement(Conn.java:383)
    at slick.jdbc.JdbcBackend$SessionDef.prepareStatement(JdbcBackend.scala:321)
    at slick.jdbc.JdbcBackend$SessionDef.prepareStatement$(JdbcBackend.scala:311)
    at slick.jdbc.JdbcBackend$BaseSession.prepareStatement(JdbcBackend.scala:433)
    at slick.jdbc.StatementInvoker.results(StatementInvoker.scala:32)
    at slick.jdbc.StatementInvoker.iteratorTo(StatementInvoker.scala:21)
    at slick.jdbc.Invoker.foreach(Invoker.scala:47)
    at slick.jdbc.Invoker.foreach$(Invoker.scala:46)
    at slick.jdbc.StatementInvoker.foreach(StatementInvoker.scala:15)
    at slick.jdbc.StreamingInvokerAction.run(StreamingInvokerAction.scala:22)
    at slick.jdbc.StreamingInvokerAction.run$(StreamingInvokerAction.scala:20)
    at slick.jdbc.SQLActionBuilder$$anon$1.run(StaticQuery.scala:95)
    at slick.jdbc.SQLActionBuilder$$anon$1.run(StaticQuery.scala:95)
    at slick.basic.BasicBackend$DatabaseDef$$anon$2.liftedTree1$1(BasicBackend.scala:242)
    at slick.basic.BasicBackend$DatabaseDef$$anon$2.run(BasicBackend.scala:242)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

, потому что SQLite не разрешает параллельный доступ, как я могу предотвратить одновременный доступ slick к моей базе данных SQLite?

Что я делаю, это следующее:

У меня есть Akka Flow, который подключен к приемнику акторов, который использует сеанс, неявно предоставленный для выполнения нескольких запросов (вставка и четыре выбора)для понимания ниже используется псевдокод, иллюстрирующий то, что я пытаюсь объяснить

val dbConnector = system.actorOf(DBConnector.props)

val sinkDBConnetor = Sink.actorRefWithAck(dbConnector, "init", "ack", "complete", println)

val sqlSink = Flow[TDM[Instant, BucketedStats[Stats.SimpleStats]]]
    .map(e => UpdateTypicalHR(e.key.get.toLong, e.when.get.from.getEpochSecond(), e.value.stats.max))
    .to(sinkDBConnetor)

class DBConnector extends Actor with ActorLogging {  
    override def receive: Receive = {
        case UpdateTypicalHR(watch_id: Long, timestamp: Long, value: Double) =>
            val request =
            (for {
                _ <- insertHr(watch_id, timestamp, value)
                t <- typicalHr(watch_id, timestamp)
                a1 <- checkDailyVariation(watch_id, timestamp)
                a2 <- check8HoursVariation(watch_id, timestamp)
                a3 <- checkHourlyVariation(watch_id, timestamp)
            } yield (t, a1 ++ a2 ++ a3)).transactionally
            session.db.run(request).onComplete {
            case Success((typical, alerts)) =>
                log.debug("Read Intic")
                sender() ! "database is free"
            case Failure(exception) =>
                session.close()
                sender() ! "database is free"
            }
    }
}
...