読者です 読者をやめる 読者になる 読者になる

Screaming Loud

研究・プログラミングなど気づいたことをメモをしています

slickでコネクションプーリング

scala slick MySQL

slickでコネクションプーリングを使おうとしても、slick自体ではサポートしていない。
Connections / Transactions — Slick 2.0.0-M3 documentation

そこで、リンク先にも書いてあるように、Javaの資産であるコネクションプーリング用ライブラリが必要になる。

枯れているCommons-dbcpを試してみた。

導入方法に関しては、ググるとたくさん出てくるが、一応載せておく。

まず、DBの接続部分に関して。
複数のDBにつなげるようにメソッドを切り出している。

application.confはこんな感じ

object HogeDao with DBConnection {
  def findById(id: Int, db:DataSource): Option[E] = {
    hogeDb.withSession { implicit session =>
      query.filter(_.id === id).firstOption
    }
  }
}

こんな感じで呼び出す。

ハマったポイント

1,インスタンスの生成に注意

上のDBConnection.scalaでは、BasicDataSourceのインスタンス生成をobjectの中でやっている。
これをtraitの中で行ってはいけない。
シングルトンであるobjectの中で定義することで、BasicDataSourceを使い回し、connection poolを管理する。
しかし、traitの中で呼び出してしまうと、hogeDbがDaoなどで複数回呼ばれると、呼ばれた回数だけインスタンスが生成される。
結果、MySQL上でshow processlistを実行すると分かるように、呼ばれた回数だけコネクションが張られてしまう。
またlazy valを使い、繋がないDBに関しては、一度つなぐまでインスタンス生成を行わないようにしている

2,closeすべし

これは、scalaというより、DB自体の話。
connectionをcloseするとプールに返却されるので、closeしない限りコネクションプールの管理対象に戻らない。
Slickの非推奨のManualでコネクションを張っていると、closeし忘れが発生してしまうので、そこは要注意。
また、sessionを使いまわすとおかしなことになるので、注意。
まず、非推奨なので、使わないことをおすすめする。

所感

C3P0も試したが、同じような感じで導入できた。
HikariCPも今度試してみるかも。

ここ間違ってるってところがあれば、指摘お願いしますm(_ _)m