PlayFramework2.1.3(Java)+JPA 使ってみる #2

play2.1(Java)でJPAを使ってみたメモの続き。

コントローラーから検証#1

UnitTestをあきらめて、コントローラーからDBアクセスを検証してみる。

app/controllers/Application.java

public class Application extends Controller {
    public static Result tests()
    {
        Company company = Company.findById(1L);
        if (company == null) {
            return notFound();
        }
        return ok(company.name);
    }
}

conf/routes

GET     /tests                       controllers.Application.tests()

play1のような感覚で実装できた。コントローラーメソッドの戻り値が void から Result に、Result は Exceptionでなくなった。
play1 の throw result は面白かったけど throw this のような違和感があった。独自Resultクラスで throw this と書いたことがあります。やめたけど。

http://localhost:9000/tests にアクセスすると、

[RuntimeException: No EntityManager bound to this thread. Try to annotate your action method with @play.db.jpa.Transactional]

と表示された。親切なメッセージだなあ。

testsアクションを @play.db.jpa.Transactional でアノテートとする。これはドキュメントにも載っている通り。2.3のころにはアノテートしなくてもよくなるかな。

アノテートして http://localhost:9000/tests へ。

[PersistenceException: org.hibernate.exception.SQLGrammarException: could not load an entity: [models.Company#1]]

h2データベースに接続したみたいだ。SQLGrammarException は create table も insert もしていないので当然か。

コントローラーから検証#2

コントローラーでDDLとテストデータを投入してみる。JPA.em() で EntityManager 取得できるのは play1と同じ感覚。

    @play.db.jpa.Transactional
    public static Result tests() {
        String sql1 = "create table company ( "
                + "id bigint not null, "
                + "name varchar(255), "
                + "constraint pk_company primary key (id))";
        String sql2 = "insert into company (id,name) values (  1,'Apple Inc.')";
        JPA.em().createNativeQuery(sql1).executeUpdate();
        JPA.em().createNativeQuery(sql2).executeUpdate();

        Company company = Company.findById(1L);
        if (company == null) {
            return notFound();
        }
        return ok(company.name);
    }

コントローラーでテストデータ投入#2

    @play.db.jpa.Transactional
    public static Result tests()
    {
        Company c = new Company();
        c.id = 2L;
        c.name = "asdf";
        c.save();

        Company company = Company.findById(2L);
        if (company == null) {
            return notFound();
        }
        return ok(company.name);
    }

DDL自動生成

play1 にあった jpa.ddl=create-drop をやりたい。
conf/META-INF/persistence.xml に次を加えたらできた。

        <properties>
            <property name="hibernate.hbm2ddl.auto" value="create-drop"/>    <--- 追加
        </properties>

DDL自動生成ができると、おおよそのモデルができるまで evolution 作成を先延ばしにできるので捗る。