Kuina-Dao 開発記 全件取得と任意の条件検索

ちょっと停滞気味の Kuina-Dao 開発記.
次は Query by Example に進むはずだったのですが,そのためにはエンティティのメタデータが必要で,そこがネックになって停滞中です.心より恥じる.
エンティティのメタデータを扱うのに便利な APIJPA に含まれていれば大助かりなのですが,残念ながらかけらもありません.
そんなわけで (どんなわけで?),自力でリフレクションしようかと思ったのですが,それはそれで面倒な上に,マッピングファイルを使われると破綻してしまいます.
ちなみに,Hibernate には org.hibernate.metadata.ClassMetadata とかあって,比較的簡単にエンティティのメタデータを利用することができます.
そんなわけで (どんなわけで?),エンティティのメタデータに関しては JPA 実装の API を使うことにして,S2Tiger にその抽象レイヤを持っておくのがいいかな,と思ったり.
id:taedium さんも同じような課題に直面しているようなので,S2-Tiger も含めてどう対応するか,JavaEE 勉強会で相談しようと思っていたのですが,taedium さん欠席だったのでできず終い.
っていうのが相談内容でした>taedium さん


ともあれ (JW),何も進捗がないのは寂しいので,簡単なところを済ませておこうということで,全件取得機能を追加しました.

public intarface EmployeeDao {
    List<Employee> findAll();
    ・・・
}

というように,名前が 'findAll' で引数のないメソッドを DAO に定義すると,

SELECT employee FROM Employee employee

という JPQL を発行します.


先日の JavaEE 勉強会で t-wada さんの披露した GoyaGen ですが,それはテーブルの定義から次の 3 種類のファイルを生成するそうな.

  • Criteria
  • Dao
  • SQL

ここで,Criteria というのは次のような JavaBeans.

public class EmployeeCriteria {
    private String equalName;
    private String notEqualName;
    private String likeName;
    private String notLikeName;
    ...
}

うる憶えなのでフィールド名は間違ってるかも.
ともあれ (JW),こんな風にエンティティの一つのプロパティに対して様々な問い合わせ条件を指定できるように,多数のプロパティを持つのが Criteria.
自動生成ならではの力業.(^^;
んで,

    criteria.setLikeName("A%");
    List list = dao.find(criteria);

みたいに使う模様.
んで,一緒に生成される SQL ファイルには

/*IF equalName != null*/name = /*equalName*/'hoge'/*END*/
/*IF notEqualName != null*/name <> /*notequalName*/'hoge'/*END*/
/*IF likeName != null*/name like /*likeName*/'hoge'/*END*/
/*IF notLikeName != null*/name like /*notLikeName*/'hoge'/*END*/
・・・

なんて SQL が定義されていて,Criteria で指定したとおりの条件で検索が行われるらしい.


そうかー.
S2DaoSQL 自動生成だと,条件式は = しか作ってくれないと思うのですが,やっぱりそれだけじゃ足りないのね.
Kuina-Dao としては Criteria API を提供しているので,生成される EmployeeCriteria みたいなのの中でそれを使えば Dao や SQL ファイルなしで同じようなことができるかなーと思うわけですが,自動生成の力を借りなくても柔軟な問い合わせを DAO でやりたいという要望もあるんじゃないかということで,こんな風にしてみました.

public interface EmployeeDao {
    List<Employee> findCondition(ConditionalExpression... conditions);
    ・・・
}

ConditionalExpression というのは Kuina-Dao の Criteria で提供している型.
なので,CriteriaOperations のメソッドを static import することで,

    List<Employee> dao.findCondition(between("height", 150, 170), or(lt("weight", 45), gt("weight", 70)));

のように使うことができます.
Criteria 同様,複数並べられた条件は AND で連結されます.


GoyaGen の生成する Criteria には ORDER BY を指定するためのプロパティもあったような気のせいが.
これをどうするかは頭が痛い...
Java5 の可変長引数は引数並びの最後の一つだけなので,

    List<Employee> findCondition(ConditionalExpression... conditions, OrderbyItem... orderbyItems);

みたいなことができないんですよね.
やるならせいぜい

    List<Employee> findCondition(ConditionalExpression[] conditions, OrderbyItem[] orderbyItems);

みたいな感じか.
うーん,あまり嬉しくないような.
これを DAO のメソッドで直接表現するのはちょっと保留かなぁ.
Criteria API もあることだし...