PlayFramework2.1.3(Java)+JPA 使ってみる #1
Play 2.x RoadmapによるとPlayFramework2.3(Java)では、EBeanでなくJPAが推奨されるようです。職場ではplay1を使っているが、play2でJPAを使えるなら移行しやすいかもしれない。2.3を待たずPlayFramework2.1.3(Java)+JPAでどれだけやれるか試そう。と思った。
以下は、play2.1(Java)でJPAを使ってみた時のメモです。
アプリケーション作成
Play のインストールのつぎにアプリケーション作成する。
$play2 new jpaprac1
コマンドも結構変わってるみたいね。playコマンドでplayコンソールに入り、実行するコマンドもあるようだ。
ディレクトリ構成はplay1と似てる。projectディレクトリとtargetディレクトリが増えたな。
JNDI を経由してデータソースを公開する
play2でJPAが使えるかどうかを検証することが目的なので、コントローラー、ビューは飛ばしてモデル周りを見ていく。
ドキュメント通りにやる。
conf/application.conf
db.default.driver=org.h2.Driver db.default.url="jdbc:h2:mem:play" db.default.jndiName=DefaultDS jpa.default=defaultPersistenceUnit
[2013.8.30] 追記 ドキュメントに書いてないけど `jpa.default=defaultPersistenceUnit` も追加する。
play1から見慣れた application.conf な感じ。play2はマルチDBがサポートされたので default は接続先名なんだろう。
フレームワークIDははくなった、といつかどこかで聞いた気がする。
JPA の実装をプロジェクトに追加する
play2.1はJPA関連に依存していないので、使用ライブラリに追加する必要があると。
ドキュメントに書いて無くてちょっと躓いたが、これは project/Build.scala を編集する。
samples/java/computer-database-jpa の project/Build.scala
import sbt._ import Keys._ import play.Project._ object ApplicationBuild extends Build { val appName = "computer-database-jpa" val appVersion = "1.0" val appDependencies = Seq( javaCore, javaJdbc, javaJpa, "org.hibernate" % "hibernate-entitymanager" % "3.6.9.Final" ) val main = play.Project(appName, appVersion, appDependencies).settings( ebeanEnabled := false ) }
依存ライブラリは conf/dependencies.yml でなくここに書くことになったのか。conf/application.conf に書いてた name, version もここに書くと。
Build.scala を編集したらplay reload (または playコンソールでreloadコマンド)する。と、次回testしたとき依存ライブラリが解決されるようだ。
runのときは「auto-reloading」してくれる。とりあえず reload コマンドは覚えておこう。ライブラリを追加したら play eclipse もしておくとよさそうだ。
永続性ユニットを作成する
ドキュメント通りにやる。
samples/java/computer-database-jpa の persistence.xml をコピペでもいい。
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0"> <persistence-unit name="defaultPersistenceUnit" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <non-jta-data-source>DefaultDS</non-jta-data-source> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect"/> </properties> </persistence-unit> </persistence>
play.db.jpa.JPA ヘルパーを使う
ドキュメント通りにやる。あるいは samples/java/computer-database-jpa の Company.java を参考にする。
@Entity public class Company { @Id public Long id; @Constraints.Required public String name; public static Company findById(Long id) { return JPA.em().find(Company.class, id); } public void save() { JPA.em().persist(this); } }
play2.1.3 にはJPA用のModelクラスがないので、そのうち自作する必要がありそうだ。
ユニットテスト(できなかった)
DDLも作っていないが、ここまでをテストしてみる。DBに接続できない、テーブルがないくらいは出るだろうか。
samples/java/computer-database-jpa の ModelTest.java を参考にした。
public class ModelTest { @Test public void findById() { running(fakeApplication(), new Runnable() { public void run() { JPA.withTransaction(new play.libs.F.Callback0() { public void invoke() { Company asdf = Company.findById(1L); assertThat(asdf.name).isEqualTo("asdf"); } }); } }); } }
これが噂の fakeApplication か。これはうざい。
play2のテスト実行はplayコンソールで test。しかし、テストされずスルーされてしまった。
[info] ModelTest [info] [info] [info] Total for test ModelTest [info] Finished in 0.001 seconds [info] 0 tests, 0 failures, 0 errors [info] Passed: : Total 0, Failed 0, Errors 0, Passed 0, Skipped 0
テストクラスは拾われたが、メソッドがスルーされてる。@Testアノテートしているのになぜだろう。
Eclipseからテストしたらテストできたようだ。これはあとで調査しよう。