[Seasar-user:2366] Re: 【 S2Dao 】「要望・提案」 A-DaoMetaData & B-JOIN アノテーション

kubo@buildsystem.jp jazzflute
2005年 7月 15日 (金) 12:09:51 JST


久保です。


> [B]

> これって、たとえばNO_PERSISTENT_PROPSアノテーションでdepartment(か
> Deptno)が指定されていたらJOINを行わないようにすれば、目的は達成できるで
> しょうか。
はい、達成されます。

public static final selectEntity_NO_PERSISTENT_PROPS = "department, ...";

見た目は、「何を結合するか」の方がわかりやすいのですが、
デフォルトはフル結合なので、そこから「何を結合しないか」の方が
今となっては良いのかもしれません。

> アノテーションの追加は学習コストが上がるのと、一度追加すると容
> 易に変更できないので慎重にすべき
理解しました。




> [A]

> あとでやっておきます。
> S2Daoのアノテーション対応も控えていることですし、S2Daoをできるだけ拡張し
> やすいように変更していこうと思ってるんで何かありましたらどんどん提案して
> ください。

ありがとうございます。


> できれば、どのような拡張を行おうと思っているのか教えてもらえれば幸いです。

また、長くなりますが、しっかり自分のやろうとしていることを
話した方が良いですね。

自分はTorqueのGeneratorを改良して、S2Daoの「EntityとDaoとdao.dicon」、
加えてSearchCondition(ConditionBeanと呼んでいる)を自動生成するツールを
作っています。今度ある企業のシステム標準化に採用される予定です(大規模です)。
採用はほぼ決定ではありますが、やはりライバルはHibernateやTorque(など)です。
それらO/Rマッパーでずっと開発してきた人もいます。
その人たちの意見を聞くと、やはり

・EntityはGenerationGapで自動生成で、開発中のDB変更も簡単でないと。
・単純なSQLをいちいち書くのは効率が悪い。外部ファイルが増えるのもつらい。

という話になり、それは自分も同感できます。ただ、自分の意見として別に...
業務システムでは複雑なSQLが頻繁に登場するが、それらをCriteriaなどで
Javaソース上で無理やり組み立てるやり方に対し、

・メンテナンス時に直感的にわかりにくい。実行してログみないとSQLが見えない。
・Criteriaで工夫するより、SQLを書いたほうが早く、SQLツールでテストしやすい。

という考えを抱いています。
それらを折衷した考え方として、

[#] AND条件のみで構成されるSQLは自動生成されたものだけで検索可能

[$] GroupingやOR条件・副問合せの含まれるSQLは、[.sql]でしっかりSQLを記述。
     - 業務上キモになるSQLなので、他のO/Rマッパーには無いS2Daoの
       機能を使って、(SQLコメントを利用し、テスト値を埋め込んだ)SQLを
       外部ファイルに残しておく(メンテ時のドキュメントにもなる)。

という方針を打ち立てて提案したところ、理解を得ることができました。
めでたく、S2Dao採用となったわけですが、[#]の機能をどうにかしないと
いけません([$]に関してはS2Daoをそのまま利用すればOK)。
S2Daoの「SQL自動生成」機能は、Equal[=]によるAND条件のみです。
それをEqual/NotEqual/IsNull/IsNotNull/GreaterThan/...などの
演算子もサポートするようにを拡張いたしました。
以下のようなDBアクセスを、プログラマは他に何も作成せずに実行する
ことができます。

ex. 部門マスタ{PK: 部門コード&部門開始日}
    :現在、有効である部門のリスト検索。(部門レイヤ-昇順)
      (画面のコンボボックスなどに利用)
  MsDepartmentCB cb = new MsDepartmentCB();
  cb.setDepartmentStartYmd_LessEqual(systemYmd)
  cb.setDepartmentEndYmd_GreaterEqual(systemYmd);
  cb.addOrderByAsc(MsDepartmentCB.departmemtLayer_COLUMN)
  List valieDepartmentList = dao.selectList(cb);

  ※MsDepartmentCB・MsDepartmentDaoクラスは自動生成される。
  ※他にcb.lockForUpdate(), cb.fetchFirst(int n)も利用できる。

この場合、Where句がDaoで隠蔽されないので再利用性を考えるなら、
MsDepartmentBusinessなる対抗クラスを作り、データに対する振舞い
を局所化する必要がありますが、自分の周りのプロジェクトでは
その構成(クラス設計)が多いので、特に問題になりません。
ただ、設計によっては「画面IDの付いた画面対抗クラス」や
「バッチのコントローラ」がDAOに直接アクセスする設計も
あると思うので、特に提案せず、自動生成ツールの提供する機能として
自分で拡張することにしました。
(このやり方はConditionBeanを自動生成できないと大変)。

具体的には、DaoMetaDataImpl#createAutoSelectSqlByDto()の条件を
作成しているところで、以下のように実装しています。
--------------------------------------------------------------------------
	if (propertyName.endsWith("_IsNull")) {
	    buf.append(" is null");
	} else if (propertyName.endsWith("_IsNotNull")) {
	    buf.append(" is not null");
	} else {
	    buf.append(" ").append(getComparison(propertyName)).append(" /*");
		buf.append(propertyName);
		buf.append("*/null");
	}

protected String getComparison(String propertyName) {
    final String comparison;
                	
	if (propertyName.endsWith("_GreaterThan")) {
		comparison = ">";
                          	
	} else if (propertyName.endsWith("_GreaterEqual")) {
		comparison = ">=";
                  	
	} else if (propertyName.endsWith("_LessThan")) {
		comparison = "<";
                  	
	} else if (propertyName.endsWith("_LessEqual")) {
		comparison = "<=";
                  	
	} else if (propertyName.endsWith("_NotEqual")) {
		comparison = "!=";
                  	
	} else if (propertyName.endsWith("_LikeSearch")) {
		comparison = "like";
          	
	} else {
	    comparison = "=";
	}
	return comparison;
}
--------------------------------------------------------------------------

これら正常に動作しております。
実際には、この部分はVelocityで生成されるので、どのようなSuffixでどの演算子に
なるかは、自動生成ツールのプロパティとなります。プロジェクトによっては要らない
という場合もあるかもしれないので、プロパティでOFFにするとデフォルトのS2Daoに
なります。


というようなアプローチで自分はS2Daoを広めていきたいなと考えている次第です。
(他のO/Rマッパーに慣れてた人に受け入れられるような)




Seasar-user メーリングリストの案内