かとじゅんの技術日誌

技術の話をするところ

S2AsbtractServiceの使い方について

以下について誤解のないように書いておきます。

シンプルな問い合わせは、メソッドにしない。

Serviceクラス使ってる意味なくね?

aaSerivce.selectById(aaId);

というように、ID指定で取得するような問い合わせは、

selectById()メソッドを作らず、

aaService.select().id(aaId).getSingleResult();

って書くんだと。なんでも、メンテナンスコストが下がるとかで。

逆だろ、上がるだろこれ。

これすごくわかります。私も結構悩みました。本来は個人事業主さんのいう姿がよいと思います。

が、ここから本題。
私も最初のころはselectByIdをAbstractServiceにつくっていました。selectByIdって便利ですね、でもFKで関連しているテーブルもJOINしたいのですができないみたいなんですが、、、何かよいメソッドありますか?となって、、、AbstractService#joinEntityなんてメソッドを作りました。次はfindAllでORDER BYをさせてほしいという要求が出てきてAbstractService#orderByメソッドも作成しました。要するにAbstractServiceが肥大化してきてメンテナンスしにくくなってきました。

こういう話をすると個々のServiceに個別に定義するメソッド(たとえばselectById)の中でJOINもODER BYもすればいいじゃんと思うかもしれませんが、それはそれで末端の各Serviceで結構コードを書くことになると思うんですよ。

public class EmpService extends AbstractService<Emp> {
	public Emp selectById(Object... id){
		return select().id(id).getSingleResult();
	}
	public Emp selectByIdWithDept(Object... id){
		return select().join("dept").id(id).getSingleResult();
	}
}

public class DeptService extends AbstractService<Dept> {
	public Dept selectById(Object... id){
		return select().id(id).getSingleResult();
	}
	public Dept selectByIdWithCompany(Object... id){
		return select().join("company").id(id).getSingleResult();
	}
}

このレベルのコードでもエンティティの数が半端ないと手では書いてられません。
そういう意味でAbstractServiceをジェネリックDao的にきれいにできればよかったのですが、正直、工数も時間もない中でバランス良い選択肢を取るためにあえて、SELECT系はselect()メソッドをそのまま利用すべきだというのが私とチームの判断でした。一般論はそうであっても個別論は違うというお話ですなぁ〜w
(じゃぁ、JdbcManagerを直接使えばよいじゃないかというツッコミが入りそうですが、エンティティ共通で処理しなければならない要件があったり、論理削除メソッドなども用意しているのでServiceとして実装するのは必要なんですよね)

「シンプルな問い合わせは、メソッドにしない」というのは、S2JDBCのコミッタの間では推奨されていません。コメントによると個人事業主のつぶやきさんのプロジェクトの規約のようですね。

Serviceを利用する場合、使うほうは、select().id(aaId).getSingleResult()のように流れるようなインターフェースを使うのではなくて、ServiceにselectById()を作り、それを利用するほうがお勧めです。

なぜかというと、EntityごとのServiceを使う意味は、あるEntityに関する知識をそこに集約するためだからです。使うほうは、メソッド名だけ知っていればよく、その中身を意識しないようにすることが重要です。

じゃないとServiceを作る意味がなくなります。

一般論でいえば、ひがさんの意見は大賛成です。でも、プロジェクトの都合により当てはまらない場合もあるかと思います。なので、select()も使うことができるという選択肢が提供されているとよい気がします。