Play Framework 2.3 For Java ことはじめ #5 データベース接続(Spring Data JPA)編
Play Framework 2.3 For Java 入門記事一覧
第5回は、Java標準のJPAの実装の一つであるSpring Data JPA
を使ってデータベースに接続します。
Java Persistence API(JPA)とは、関係データベースのデータを扱う Java SE および Java EE のアプリケーションを開発するためのJava用フレームワークである。
あれ?JPA のアノテーションを使ってるって書いてあったEBeanもJPAなんじゃないの?と思ってしまいますが、EBeanはただ単にJPAと同じアノテーションを使ってるというだけみたいです。
JPAは仕様でそれを実装したプロダクトが色々あると言われてもなんかピンとこなかったんですが、同僚に教えてもらったり、Stack Overflow見てやっと概念が分かった気がする。
JPA is the dance, Hibernate is the dancer.
http://t.co/puyrKfUDrC
— オオシママサト (@_mpon) 2014, 7月 21
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.conf
にdb.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.sbt
にpostgresqlのドライバーを追加する。
"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.java
とPersonRepository.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.xml
でhibernate.html2ddl.auto
をupdate
にしてたからみたい。
hibernate.hbm2ddl.auto は、実行時にテーブルなどの作成を行うかどうか。
開発中は update、運用時は none、開発環境で作り直すときは create-drop を指定するとよい。update を指定すると、テーブルなどが存在しなければ自動的に作成。
create-drop を指定すると、削除して再作成する。
none を指定すると、何もしない。
と説明されていました。参考になりました。これは、DDLでさえも隠蔽してしまおうというHibernateの陰謀なのではないかと疑いたくなる機能ですなw
まとめ
JPAの仕様というか、HibernateとPostgreSQLの設定の仕方?が分かっていればこんなにはまらずにすんだなという感じです。EBeanがいいのかJPAがいいのかは、今の時点では判断できないー。一旦公式のチュートリアルのHibernateだけのJPAサンプルをやってみるか。
ということで第6回はこちら -> Play Framework 2.3 For Java ことはじめ #6 データベース接続(JPA with Hibernate)編