S2JDBCのプロパティ名をタイプセーフにする方法

s2jdbc-genでいろいろクラスを自動生成できるようになったので、S2JDBCのプロパティ名をタイプセーフにする案を考えて見ました。あくまでも、案です。
プロパティ名をあらわすPropertyNameクラスを作ります。


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;
}
}

このクラスを利用して、個別のエンティティのプロパティ名を返すクラスをs2jdbc-genで自動生成します。

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");
}
}


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");
}
}

EmployeeServiceの$n()でEmployeeNamesにアクセスできるようにします。

public class EmployeeService extends AbstractService {
public EmployeeNames $n() {
return new EmployeeNames();
}
}
これで、プロパティにアクセスするときには、$n().id()、$n().department().id()のようにタイプセーフにアクセスできます。関連はどれだけネストしても大丈夫です。
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 = ?))

のように展開されます。