EzJDBCのSQL自動生成機能の弱点と克服方法!


本日は、EzJDBCのSQL自動生成機能の弱点について説明したいと思います。

その弱点とはSQL自動生成機能はSQLのカスタマイズが出来ない事にあります。

例えば、以下の関係の2テーブルが存在したとします。

【テーブル】
 1.CUSTOMERテーブル
 2.ORDERテーブル

【テーブル関係】
 1.CUSTOMERテーブル : ORDERテーブル = 1:n

【テーブルのレコード数】
 1.CUSTOMERテーブル :10万件
 2.ORDERテーブル     :15万件

この様なテーブル関係で以下の条件にあるデータの照会を行ったとします。

【抽出条件】
 1.お客様名(CUSTOMER.NAME)が「TAKAHASHI」で始まるデータのみ抽出

【照会内容】
 1.お客様名(CUSTOMER.NAME)
 2.注文番号(ORDER.NO)

照会する標準的なEzJDBCコードは以下の通りです。

CUSTOMER CS = new CUSTOMER("CS");
List list = EzJDBC.selects(CS.name,CS.OD.no).from(CS.OD)
                 .where(CS.name.like("TAKAHASHI%")).find(Customer.class);

上記コードにより発行されるSQLは以下の通りです。

SELECT
   CS.NAME,OD.NO
FROM
   CUSTOMER as CS left join ORDER as OD on (CS.ID = OD.CUSTOMER_ID)
WHERE
   (CS.NAME like 'TAKAHASHI%')

見て分かる通り非効率です><


【非効率な理由】
 上記SQLでは、以下の順番で処理が行われます。
 1.CUSTOMERは10件レコードとORDERは15万レコードの結合を行います。
 2.結合した結果から対象となるデータを抽出します。

本来であれば、以下の様にSQLをカスタマイズいたくなります(レスポンスが良くなるため)。

SELECT
   CS.NAME,OD.NO
FROM
   (SELECT
      CUSTOMER.NAME
   FROM
      CUSTOMER
   WHERE(CS.NAME like 'TAKAHASHI%')) as CS
      left join ORDER as OD on (CS.ID = OD.CUSTOMER_ID)

EzJDBCのSQL自動生成機能には、上記SQLを作成するための機能がありません。
ということで、EzJDBCでは弱点を克服するために以下の対応を追加します。

【対応方法】
抽出条件が指定されたテーブルは、結合前に抽出条件を設定しデータを絞りこんだ後に全体の結合を行うようにする。

と思ったのですが、これだと利用者の考えたとおりSQLが作成されなくなり、混乱を招きかねません。

よって、利用者がEzJDBCに明示的に指定できる方法にしました。

上記カスタマイズを行うSAMPLE CODE

CUSTOMER CS = new CUSTOMER("CS").where(CS.name.like("TAKAHASHI%"));
List list = EzJDBC.selects(CS.name,CS.OD.no).from(CS.OD)
                 .find(Customer.class);

これでEzJDBCのSQL自動生成機能でもSQLレベルのカスタマイズが可能になります。
実装はこれからですが…(^^;)


このネタは、id:dkfjさんが下記のエントリをEzJDBCに置き換えて対応方法を考えてみました

S2JDBCのSQL自動生成で、結合条件を変えたい - プログラマでありたい

S2JDBCSQL自動生成機能は、基本的に素晴らしいです。はるか昔にHibernateを使った時のもどかしさは、ほとんどありません。ただ、たまーに結合のチューニングしたいなぁと思うことがあります。
中略...