S2JDBCのプロパティ名をタイプセーフにする方法
s2jdbc-genでいろいろクラスを自動生成できるようになったので、S2JDBCのプロパティ名をタイプセーフにする案を考えて見ました。あくまでも、案です。
プロパティ名をあらわすPropertyNameクラスを作ります。
このクラスを利用して、個別のエンティティのプロパティ名を返すクラスをs2jdbc-genで自動生成します。
package org.seasar.extension.jdbc.name;public class PropertyName {
protected String name;
protected PropertyName parent;
public PropertyName() {
this(null);
}public PropertyName(String name) {
this.name = name;
}public PropertyName(PropertyName parent, String name) {
this.parent = parent;
this.name = name;
}public String toPropertyName() {
if (parent == null) {
return name;
}
String parentName = parent.toPropertyName();
if (parentName == null) {
return name;
}
return parentName + "." + name;
}
}
package org.seasar.extension.jdbc.where;import org.seasar.extension.jdbc.name.PropertyName;
public class DepartmentNames extends PropertyName {
public DepartmentNames() {
}public DepartmentNames(PropertyName parent, String name) {
super(parent, name);
}public DepartmentNames(String name) {
super(name);
}public PropertyName id() {
return new PropertyName(this, "id");
}
}
EmployeeServiceの$n()でEmployeeNamesにアクセスできるようにします。
package org.seasar.extension.jdbc.where;import org.seasar.extension.jdbc.name.PropertyName;
public class EmployeeNames extends PropertyName {
public EmployeeNames() {
}public EmployeeNames(String name) {
super(name);
}public EmployeeNames(PropertyName parent, String name) {
super(parent, name);
}public PropertyName id() {
return new PropertyName(this, "id");
}public DepartmentNames department() {
return new DepartmentNames(this, "department");
}
}
これで、プロパティにアクセスするときには、$n().id()、$n().department().id()のようにタイプセーフにアクセスできます。関連はどれだけネストしても大丈夫です。
public class EmployeeService extends AbstractService {
public EmployeeNames $n() {
return new EmployeeNames();
}
}
innerJoin()なども、innerJoin($n().department())のように記述できます。
$n()はサービスから、エンティティのプロパティ名にアクセスするためのショートカットメソッドで、今のところ超適当な名前です。
また、WHERE句もこれを使って簡単に組み立てられるようになります。例えば、and(Where... children)は、引数の条件をANDで展開します。or(Where... children)も同様です。
は
and(or(eq($n().id(), 1), eq($n().id(), 2)),
or(eq($n().department().id(), 3), eq($n().department().id(), 4)))
((id = ? OR id = ?) AND (department.id = ? OR department.id = ?))
のように展開されます。