NetBeans 6.8でJPAの生成されるコード

エンティティクラスは替わっていない模様。
ただし、ファサードクラスの生成されるコードが変わってる。


これは「持続性」カテゴリの中にある「エンティティクラスのセッションBean」や「エンティティクラスからのJSFページクラス」で自動生成されるもの。
http://shin.cside.com/diary/2009/1018-01.png

コードを丸ごと乗せてみる。

package facadetest;

import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;
import jpa.Customer;

@Stateless
public class CustomerFacade {
    @PersistenceContext(unitName = "HogePU")
    private EntityManager em;

    public void create(Customer customer) {
        em.persist(customer);
    }

    public void edit(Customer customer) {
        em.merge(customer);
    }

    public void remove(Customer customer) {
        em.remove(em.merge(customer));
    }

    public Customer find(Object id) {
        return em.find(Customer.class, id);
    }

    public List<Customer> findAll() {
        CriteriaQuery cq = em.getQueryBuilder().createQuery();
        cq.select(cq.from(Customer.class));
        return em.createQuery(cq).getResultList();
    }

    public List<Customer> findRange(int[] range) {
        CriteriaQuery cq = em.getQueryBuilder().createQuery();
        cq.select(cq.from(Customer.class));
        Query q = em.createQuery(cq);
        q.setMaxResults(range[1] - range[0]);
        q.setFirstResult(range[0]);
        return q.getResultList();
    }

    public int count() {
        return ((Long) em.createQuery("select count(o) from Customer as o").
                getSingleResult()).intValue();
    }

}

見てわかるとおりCriteriaを使うようになっている。ただし、findRangeが配列を引数にとる意味がわからない。int型2つじゃダメなの?

件数取得と範囲取得が追加されているが、これはシンプルなページングを実装するため。「エンティティクラスからのJSFページクラス」を選択したときに有効になる。また、utilパッケージが作られそこにSelectItemやメッセージ管理、ページングのクラスが自動生成される。

エンティティクラスからのJSFページはこんなのが生成される。
http://shin.cside.com/diary/2009/1018-02.png
http://shin.cside.com/diary/2009/1018-03.png
Viewで表示、Editで変更モード、Destroyで削除だけれども、個人的には一覧で削除ってのはあんまり好きではないかな。Edit画面に入るとき排他がかけられるんでそこで削除のほうが、内容も確認できていていいような。

あとViewとEditは規模が大きい場合分けるほうが好き。アプリケーションによる排他制御(楽観的ロックのアプリケーション版)する場合、他の人がEditモードで開いて変更中であるというのが検出ができるから。せっかく入力しているのに変更できなかったというのは悲しいはず。

EJBファサードはいわゆるシンプルなCRUDなコードの自動生成で、実際にJPAを使うときにはこのクラスにメソッドを追加していくというスタイルになる。

複数のエンティティにまたがるロジックはこれらのクラスの上にかぶせるようなものをさらに用意してもよい。EJBのデフォルト動作は「トランザクションを開始していなければトランザクション開始、すでに開始していればそのトランザクションを使う」なので、EJBが他のEJBに注入されていても気軽に使うことができる。もちろん、指定された例外以外が出ればトランザクションロールバックされる。これらのトランザクション設定は一切必要ないのがいいところ。


ちなみにエラーを出すとこういうのが表示される。
http://shin.cside.com/diary/2009/1018-04.png
スタックトレースのほか、コンポーネントツリー、リクエストパラメータや各スコープごとに変数の内容を表示してくれる。積極的にtoString記述したいところ。

このエラーメッセージはweb.xmlに以下の記述があると表示される。NetBeansでは自動で入れてくれるようだ。

<context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
</context-param>