Play Framework 2.3 For Java ことはじめ #5 データベース接続(Spring Data JPA)編

f:id:masato47744:20140720125846p:plainPlay Framework 2.3 For Java 入門記事一覧

第5回は、Java標準のJPAの実装の一つであるSpring Data JPAを使ってデータベースに接続します。

Java Persistence APIJPA)とは、関係データベースのデータを扱う Java SE および Java EE のアプリケーションを開発するためのJavaフレームワークである。

あれ?JPAアノテーションを使ってるって書いてあったEBeanもJPAなんじゃないの?と思ってしまいますが、EBeanはただ単にJPAと同じアノテーションを使ってるというだけみたいです。
JPAは仕様でそれを実装したプロダクトが色々あると言われてもなんかピンとこなかったんですが、同僚に教えてもらったり、Stack Overflow見てやっと概念が分かった気がする。

PlayのEBeanはJPAじゃなくて、EBeanの次に出てくるJPAのサンプルJPAの仕様を実装しているHibernateでのサンプルである。
で、今回やろうとしているのは、JPAの仕様を実装しているけどHibernateとは違うSpring Data JPAというやつでやるということ。 ただ、このSpring Data JPAサンプルのbuild.sbtには、"org.hibernate" % "hibernate-entitymanager" % "3.6.10.Final"って書いてあるから結局どっちやねんって感じはあるんですが。まぁとりあえず考え過ぎもよくないのでいってみましょう。

1. activatorを使って用意されてるtemplateからアプリケーション作成

activatorでjpa-sampleって名前のアプリケーション作って、Eclipseで開けるようにする。テンプレートはplay-spring-data-jpa

$ activator new jpa-sample play-spring-data-jpa
$ activator eclipse

2. 設定ファイルにpostgreSQLの設定を入れていく

Eclipseでさっきのプロジェクトをインポートして、PostgreSQL用に設定を変えていきます。

application.confdb.default.jndiNameってのが追加されてる。(なぜかは分からない)

db.default.driver=org.postgresql.Driver
db.default.url="jdbc:postgresql://127.0.0.1/sample"
db.default.user=test
db.default.password="password"
db.default.jndiName=DefaultDS

build.sbtpostgresqlのドライバーを追加する。

"org.postgresql" % "postgresql" % "9.3-1101-jdbc41"

persistence.xmlの以下の部分にpostgreSQLの設定に変更する。ここが最初一番はまった。postgresql - Play 2.2 with Hibernate JPA and Postgres - Stack Overflow見てやっとクリアできた。dialectというやつがpostgreSQLになってないとダメみたい。

<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="default" 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.PostgreSQLDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update"/>
        </properties>
    </persistence-unit>

</persistence>

3. モデルとかは特に変更しないでサンプルそのまま

サンプルに最初からPerson.javaPersonRepository.javaが入っててこれがデータベースに関する処理をするみたい。
Person.javaはただのEntityを表すだけのクラスで、PersonRepository.javaがデータの取得や登録を担当するって考え方。
EBeanだと、Person.find.all()みたいにPersonクラスに対して処理を行うっていう捉え方だけど、このパターンを使えば、ただのデータと、データ操作する人の責任がきっちり分けられるよってことなのかな。ただこのRepositoryパターンがSpring Data JPA特有のものなのか、Hibernateでもあるのかがよく分かんない。

Person.java

@Entity
public class Person {
    @Id
    @GeneratedValue
    public Long id;

    public String firstname;

    public String surname;
}

PersonRepository.java

/**
 * Provides CRUD functionality for accessing people. Spring Data auto-magically takes care of many standard
 * operations here.
 */
@Named
@Singleton
public interface PersonRepository extends CrudRepository<Person, Long> {
}

実際にデータ取得してるところのソースはこんな感じ。レポジトリに対してメソッド呼び出して、エンティティはただのデータでしかないというのが分かりますね。

        final Person person = new Person();
        person.firstname = "Bruce";
        person.surname = "Smith";

        final Person savedPerson = personRepository.save(person);

        final Person retrievedPerson = personRepository.findOne(savedPerson.id);

4. アプリケーションの実行

なんと、これだけで、動きます。personテーブルが勝手に作られてて、データが登録されてます。

Evolutionも走りません。play_evolutionsテーブルもできてなかった。Evolutionどこいったんだ。。
データベースの中を見ると、personってテーブルと、hibernate_sequenceというのが作成されているのでHibernateがなんかやったんだろうな。Hibernate使ってる人からしたら当たり前の機能なのかな?うーんよく分からん。色々調べてたら、Hibernateの機能だってことが分かった!persistence.xmlhibernate.html2ddl.autoupdateにしてたからみたい。

Hibernateを使ったシンプルなJPA環境構築

hibernate.hbm2ddl.auto は、実行時にテーブルなどの作成を行うかどうか。
開発中は update、運用時は none、開発環境で作り直すときは create-drop を指定するとよい。

update を指定すると、テーブルなどが存在しなければ自動的に作成。
create-drop を指定すると、削除して再作成する。
none を指定すると、何もしない。

と説明されていました。参考になりました。これは、DDLでさえも隠蔽してしまおうというHibernateの陰謀なのではないかと疑いたくなる機能ですなw

まとめ

JPAの仕様というか、HibernatePostgreSQLの設定の仕方?が分かっていればこんなにはまらずにすんだなという感じです。EBeanがいいのかJPAがいいのかは、今の時点では判断できないー。一旦公式のチュートリアルのHibernateだけのJPAサンプルをやってみるか。

ということで第6回はこちら -> Play Framework 2.3 For Java ことはじめ #6 データベース接続(JPA with Hibernate)編