NetBeans6.8 BetaでJPA2.0を試してみる。 - その2
JPA2.0はまだリリースされていない状況なのでJSRのサイトにあるProposed Final Draft(最終提案ドラフト、最終ドラフト提案??)の資料を元に試していこうと思います。ちなみに英語はからきし駄目ですが、サンプルのソースコード見ればなんとかなるんじゃね?的なノリです。
今回はMetamodelを使わなくてもCriteriaAPIを使えるような部分を試してみます。まずは対象のテーブルを全件取得してみます。
・CriteriaBuilder
とりあえずCriteria APIを使うにはCriteriaBuilderというのが最初に必要らしいです。
んで、こやつはEntityManagerFactoryもしくはEntityManagerから取得できる模様。
EntityManagerFactory emf = Persistence.createEntityManagerFactory("JavaApplicationPU"); EntityManager em = emf.createEntityManager(); //EntityManagerFactoryから取得 CriteriaBuilder builder1 = emf.getCriteriaBuilder(); //EntityManagerから取得 CriteriaBuilder builder2 = em.getCriteriaBuilder();
・CriteriaQuery
んで、CriteriaBuilderからCriteriaQueryを取得するみたいです。
CriteriaBuilder#createQueryの引数には取得したいEntityのClassを指定するようです。
こんな感じ
CriteriaQuery<Customer> cq = builder1.createQuery(Customer.class);
んで、このCriteriaQueryをつかってゴニョゴニョやりながらタイプセーフにプログラミングをしていくようです。
・Root
まずはRootというオブジェクトを取得します。
Root<Customer> customer = cq.from(Customer.class);
なんかよくわかりませんがRootですw。
CriteriaQuery#fromにより取得できるオブジェクトで、Joinとかできるみたいです。とりあえず今回は無視です。
・いろいろ
んで、このRootをCriteriaQueryのselectメソッドに指定すると全件取得のCriteriaQueryオブジェクトの完了のようです。
cq.select(customer);
その後、EntityManagerのcreateQueryのメソッドの引数に渡してやり、getResultListを呼び出すとCUSTOMERテーブルの全件取得完了です。
for(Customer c :em.createQuery(cq).getResultList()){ System.out.println("customer is " + c); }
上記のcreateQueryはJPA1.0までの下記と同じになります。
em.createQuery("SELECT c FROM Customer c");
こんな単純なJPQLにどんだけ手間かけてんだよって感じですが、Criteriaの方だとgetResultListがタイプセーフなListになってます。これは個人的に結構嬉しい感じです。
・まとめ
上記までの文をまとめるとこんな感じです。
EntityManagerFactory emf = Persistence.createEntityManagerFactory("JavaApplicationPU"); EntityManager em = emf.createEntityManager(); CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<Customer> cq = builder.createQuery(Customer.class); Root<Customer> customer = cq.from(Customer.class); cq.select(customer); for (Customer cstm : em.createQuery(cq).getResultList()) { System.out.println("customer is " + cstm); }
・流れるような〜
また、CriteriaQuery作成以降はいわゆる流れるようなインターフェースとして下記のように書けます。(むしろこう書くべきでしょうが、このくらいの文だと良さが見えませんねぇ〜)
for (Customer cstm : em.createQuery(cq.select(cq.from(Customer.class))).getResultList()) { System.out.println("customer is " + cstm); }
・おまけ
おまけ、カウント取得のCriteria
CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery cq = builder.createQuery(); Root<Customer> rt = cq.from(Customer.class); cq.select(em.getCriteriaBuilder().count(rt)); System.out.println("count = "+em.createQuery(cq).getSingleResult());
また、上記は下記のように書けます。
CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery cq = builder.createQuery();
System.out.println(em.createQuery(cq.select(builder.count(cq.from(Customer.class)))).getSingleResult());
S2JDBCやJMockを使ったことある人なら取っ付きやすいかと思いますが、そうでない人は結構面食らいそうですねぇ〜。
次回こそはMetamodel使ったCriteriaやります。ほっ、本当です><