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());

S2JDBCJMockを使ったことある人なら取っ付きやすいかと思いますが、そうでない人は結構面食らいそうですねぇ〜。

次回こそはMetamodel使ったCriteriaやります。ほっ、本当です><