toString
共通の親エンティティに toString を実装し public フィールド値を出力されるようにすれば色々便利です。これは特に S2JDBC のエンティティに限ったことではありません。
@MappedSuperclass public class AbstractEntity implements Serializable { public String toString() { return <フィールドの値を連結した文字列>; } } public class Table1 extends AbstratEntity { public Long id; public String xxxCd; public String xxxNm; } Table1 table1 = ・・・; log.debug("table1の中身:" + table1);
DEBUG 2008/01/01 table1の中身:{id=123, xxxCd=A01, xxxNm=名前}
通常はデバッガを使うので不要ですが、大量のデータを一度に見たり、ログを参照するしかない状況の場合に便利です。元々、toString メソッドがデバッグ用途に用意されたものなので、これはどこでもよくやっていると思います。ただ、<フィールドの値を連結した文字列> は手でやるのは面倒なので、自動生成の選択肢が色々あります。まず実行時に解決する動的なもの。
- Jakarta Commons ToStringBuilder
- S2 Beans
次に静的に toString メソッドを生成する Eclipse プラグイン。
- Commonclipse
- Commons4E
- JUtils
今回、S2 を使っているので、どうせなら、Beans を使おう(変な使い方ですけど)ということで、こんな。
@MappedSuperclass public class AbstractEntity implements Serializable { public String toString() { return Beans.createAndCopy(Map.class, this).execute().toString(); } }
ちなみに Commons なら、こんな感じです。
return ToStringBuilder.reflectionToString(this);
これで、早速動かすとスタックオーバーフロー。。。 というかエンティティは相互参照があるので、そりゃそうですね。Table1 -> Table2 -> Table1 -> Table2 -> のような感じで、toString の呼び出しが無限ループに。結局、ちょっとダサいですが、こんなコードにしました。
public String toString() { Map<String, Object> fieldMap = new TreeMap<String, Object>(); for (Class<?> c = getClass(); c != Object.class; c = c.getSuperclass()) { for (Field field : c.getFields()) { int mod = field.getModifiers(); if (Modifier.isStatic(mod)) { continue; } Object value = FieldUtil.get(field, this); if (value == null || value instanceof String || value instanceof Integer || value instanceof Long || value instanceof Boolean) { fieldMap.put(field.getName(), value); } } } return fieldMap.toString(); }