EzJDBCへの質問と返答/備考録


社内からEzJDBCの質問があったので、質問と回答をとめたものを備考録としてメモメモします。


Q1.EzJDBC#relationする場合、個別にORDER BY句オプションが追加できればいいと思います。
A1.個別にORDER BY句オプションというのは、以下の様なことでしょうか?
   親(CUSTOMER)子(ORDER)孫(ORDER_ITEM)のテーブルを結合した時に、それぞれの並び順を指定
   するを可能にするという内容であれば、以下のように指定することが可能です。

CUSTOMER CUS = new CUSTOMER();
List list = EzJDBC.froms(CUS).join(CS.ODR.ODI)
              .where(CUS.name.like("TAKA%"))
              .orderBy(CUS.name.asc(), ORD.orderDate.desc(), ORD.no.asc())
              .find(Customer.class);


Q2.複数レコード結果が返るSQLには、ORDER BY句オプションは必須かと。
A2.なるほど検討の価値ありですね。
   その場合は、自動orderByセットを解除する機能も一緒に持とうかと思います。
   1.デフォ設定の場合は、EzJDBC#relationメソッドを利用した場合にorderByメソッドの指定
   がなかった時は、自動で親子孫...テーブルのプライマリキーをORDER BY句に設定する。
   このデフォ設定も「EzJDBC.properties」の下記の設定で切り替え可能。

# ORDER BY句自動設定有無(true:自動セットon, false:自動セットoff)
ORDERBY_AUTO_SET=true

CUSTOMER CUS = new CUSTOMER();
List list = EzJDBC.froms(CUS).join(CS.ODR.ODI)
              .where(CUS.name.like("TAKA%"))
              .orderBy(false)
              .find(Customer.class);


Q3.A2の回答についてはある意味良いとは思いますが、全て自動だと、あまりSQLを意識しなくなり開発者にとって危険だと思いますが。 
A3.ここが鬼門ですね。
   もう一つ案があるのですが、orderByメソッドを呼び出さないとfind系メソッドが
   呼び出さないようにするとか!
   方法はいたって単純なのですが、EzJDBC#orderByで帰ってくるインターフェースのみ
   find系メソッドが存在するとか。

1.JDBC1インターフェースにはfind系メソッドが存在しない
  JDBC1 jdbc1 = EzJDBC.froms(CUS).join(CS.ODR.ODI)
2.JDBC2インターフェースはfind系メソッドが存在する
  JDBC2 jdbc2 = EzJDBC.froms(CUS).join(CS.ODR.ODI).orderBy(...)


Q4.A3はORDER BY句のクセをつけるためにはいいですね。1件しか返ってこないSQLの場合は微妙かもですけど。
A4.そうですね(^^;)
   ただし、EzJDBC#from#join#relationの場合は、メイン(Root)テーブル以外のテーブルへの
   order by句は意味をなすので必要かなと。
   EzJDBC#findSingleメソッドは、orderByメソッドを呼び出さなくても良いようにするか(・・?
   微妙ですね。EzJDBC#findSingleは、結果が複数件であっても最初の1件を取得するので、
   orderByの意味は存在するので…検討事項とします。


Q5.個人的には(DB2で言えば)fetch first句は欲しいですが、そこまで行くとSQL手書きですよね。
   使い道としては、バッチ系の大量更新処理で、、、
   1.N件単位にfetchで抽出結果を制限して取得
   2.UPDATE or DELETE処理
   3.コミット
   条件に該当する結果がなくなるまで繰り返し、エラーが発生した場合でも処理単位にリカバリーする
   必要のない更新処理(再編成-削除とか)では絶大な威力を発揮します。

A5.EzJDBCで上記のことを行う場合は、2通りの方法が用意されています
   1.ページング機能による実装(EzJDBC#limitメソッドとEzJDBC#offsetメソッド)

// トランザクション開始
EzTx.begin();
// 取得するレコード数、カーソルのポインタ
int n=10; int p= 1;
CUSTOMER CS = new CUSTOMER();
// テーブルを照会
EzJDBC jdbc = EzJDBC.froms(CS).where(CS.name.eq("TAKAHASHI")).limit(n);
List list = null;
while(list = jdbc.offset(p).find(Customer.class)).size() > 0) {
  for(Customer c:list) {
    c.name="高橋";
    EzJDBC.to(CS).update(c);
  }
  EzTx.commit();
  // offset加算
  p = p+n;
}
// トランザクション終了
EzTx.end();

   2.イテレート機能による実装(EzJDBC#iteretorメソッド)

// トランザクション開始
EzTx.begin();
// 更新系SQLを10回発行する毎にcommitを行う設定
EzTx.setCommitCount(10);
CUSTOMER CS = new CUSTOMER();
// 条件とマッチするデータを10(n)件毎取得するEzJDBC
JDBCIterator jdbcIterator = EzJDBC.froms(CS)
             .where(CS.name.eq("TAKAHASHI")).iterator(Customer.class);
while(jdbcIterator.hasNext()) {
  Customer c = jdbcIterator.next();
  c.name="高橋";
  EzJDBC.to(CS).update(c);
}
// トランザクション終了
EzTx.end();

   1と2の違いは、1はSQLが複数回発行されますが、2の方法は1回のみですということです...(^^)
   用途によって使いわければよいかと思います。
   但しレスポンスは圧倒的に2の方法が良いです。。。