PlayFramework JDBCとEvolutionsマイグレーションの導入

個人開発したアプリの宣伝
目的地が設定できる手帳のような使い心地のTODOアプリを公開しています。
Todo with Location

Todo with Location

  • Yoshiko Ichikawa
  • Productivity
  • Free

スポンサードリンク

PlayFrameworkからデータベースを扱う為、JDBCドライバとマイグレーションツールEvolutionsを導入する。


依存ライブラリの導入

build.sbt

libraryDependencies += jdbc
libraryDependencies += "org.postgresql" % "postgresql" % "42.2.12"
libraryDependencies += evolutions

ドライバのバージョンは https://jdbc.postgresql.org/ この辺りから最新のバージョンを確認して指定した。


データベース DSNの指定

データソースの指定は、conf/application.confに記述する。

例えばDockerでこのようなPostgreSQLを起動して接続する場合、

$  docker run --name play-sample-db -p 5432:5432 -e POSTGRES_USER=play -e POSTGRES_PASSWORD=play -e POSTGRES_DB=playdb -v $(pwd)/pgdata:/var/lib/postgresql/data -d postgres:12.2

application.confは以下のように記述する。

db.default.driver=org.postgresql.Driver
db.default.url="jdbc:postgresql://localhost:5432/playdb"
db.default.user=play
db.default.password=play


Evolutionsでマイグレーションを定義する

マイグレーションファイルはconf/以下にevolutions/dbname/ディレクトリを作成して定義・配置する。

dbnameは例えば環境ごと(product, develop, test)にマイグレーションを変更したい場合等は個別に環境ごとのdbnameのディレクトリを作成すればよい。

exp.

/conf/
  db-product/
  db-develop/
  db-test/


マイグレーションファイルの作成

マイグレーションファイルは作成したディレクトリ以下に1.sql, 2.sql, ...と作成していく。

コメントで進行とロールバック時の挙動を指定する。

1.sql

# --- !Ups
create table people(
    id  serial primary key,
    name text not null,
    mail text not null,
    tel text
);
insert into people (name, mail, tel)values('Terry', 'terry@letitride.jp', '000-0000-0000');
insert into people (name, mail, tel)values('Mike', 'mike@letitride.jp', '111-1111-1111');
insert into people (name, mail, tel)values('Mika', 'mika@letitride.jp', '222-2222-2222');
insert into people (name, mail, tel)values('Bob', 'bob@letitride.jp', '333-3333-3333');

# --- !Downs
drop table people;

定義後、ブラウザからアクセスするとマイグレーションの実行確認を求められるので、許可すると指定のスクリプトが実行される。

尚、自動で実行したい場合、application.conf

applyEvolutions.default = true

を指定しておけばよい。


データベースの利用

PlayFrameworkからデータベースの利用は、以下のように記述する。


Fetch
import play.api.db.Database
import java.sql.SQLException

//Databaseインスタンスをinjectする
class PeopleController @Inject()(db: Database ) extends AbstractController {
...
def foo = {
    try{
      db.withConnection{ conn =>
        val stmt = conn.createStatement
        val rs = stmt.executeQuery("select * from people")
        while(rs.next){
          val id = rs.getInt("id")
          val name = rs.getString("name")
        }
      }
    }catch{
      case e:SQLException => //...error
    }
}


Write
def bar = {
    try {
      db.withConnection{ conn =>
        val ps = conn.prepareStatement("insert into people (name, mail, tel)values(?, ?, ?)")
        ps.setString(1, "name")
        ps.setString(2, "mail@domain.com")
        ps.setString(3, "00-0000-0000")
        ps.executeUpdate()
      }
    } catch{
      case e:SQLException => //...error
    }
}