PlayFramework2.1.3(Java)+JPA 使ってみる #2
コントローラーから検証#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); }