マッピング対象のフィールド名に細工する方法
デフォルトのオートマッピングでは、get/setNameというセッター・ゲッターメソッドに対してNAMEというフィールドがマッピングされる。データベースフィールド名としては、単純なNAMEなどという名称よりも、USR_NAME等の何かしらのプリフィックスを持つものとしたい。理由としては、
- 単純な名称であると、データベースの予約語と競合してしまう場合がある。
- SQLはJavaの文字列として記述されてしまうので、フィールド変更の際に検索しやすいように、単純な名称は避けたい。
例えば、テーブル自体は
create table user(f_id identity, usr_name char(80), usr_phone char(80), primary key(f_id))
などと生成し、それに対するクラスを
public static class User {
public int getId() { return id; }
public void setId(int value) { id = value; }
public String getName() { return name; }
public void setName(String value) { name = value; }
public String getPhone() { return phone; }
public void setPhone(String value) { phone = value; }
}などとしたい。つまり、セッター・ゲッターは単純な名前のままにしておきたい。
実現方法
以下のようにしてみたが、これは実験的なものであり必ずしもうまくいくとは限らない。
AClassExtra.java
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface AClassExtra {
String fieldPrefix();
}ModObjectMapper.java
import java.lang.reflect.*;
import java.sql.*;
import java.util.*;
import com.jenkov.db.impl.mapping.*;
import com.jenkov.db.itf.*;
import com.jenkov.db.itf.mapping.*;
public class ModObjectMapper extends ObjectMapper {
private String fieldPrefix;
public ModObjectMapper() {
super(new ObjectMappingFactory());
nameGuesser = new DbNameGuesser() {
@Override
@SuppressWarnings("unchecked")
public Collection<String> getPossibleColumnNames(Method member) {
Collection<String> c = (Collection<String>)super.getPossibleColumnNames(member);
if (fieldPrefix == null) return c;
List<String> list = new ArrayList<String>(c);
for (Object o: c) {
list.add(fieldPrefix + o);
}
return list;
}
};
}
@Override
public IObjectMapping getObjectMapping(Object objectMappingKey,
IPersistenceConfiguration configuration, Connection connection)
throws PersistenceException {
fieldPrefix = null;
if (objectMappingKey instanceof Class) {
Class<?> clazz = (Class<?>)objectMappingKey;
AClassExtra aClassExtra = (AClassExtra)clazz.getAnnotation(AClassExtra.class);
if (aClassExtra != null) {
fieldPrefix = aClassExtra.fieldPrefix();
}
}
return super.getObjectMapping(objectMappingKey, configuration, connection);
}
}TestZero.java
public class TestZero {
public static PersistenceManager perman = new PersistenceManager();
public static void main(String[]args) throws Exception {
perman.getConfiguration().setObjectMapper(new ModObjectMapper());
// DBドライバをロード
Class.forName("org.hsqldb.jdbcDriver");
// データベースを作成
{
DatabaseInitializer databaseInitializer =
perman.getConfiguration().getDatabaseInitializer();
databaseInitializer.add(1,
"create table user(f_id identity, usr_name char(80), usr_phone char(80), primary key(f_id))");
Connection conn = getConnection(); // setAutoCommit(true)の状態
perman.initializeDatabase(conn);
conn.close();
}
// レコードを挿入
{
Connection conn = getConnection();
conn.setAutoCommit(false);
IDaos daos = perman.createDaos(conn);
User user = new User();
user.name = "鈴木";
user.phone = "aaaa";
daos.getObjectDao().insert(user);
daos.getObjectDao().insert(user);
conn.commit();
conn.close();
}
// レコードを検索
{
Connection conn = getConnection();
IDaos daos = perman.createDaos(conn);
User user = (User)daos.getObjectDao().read(User.class,
"select * from user where f_id=0");
daos.getObjectDao().update(user);
conn.close();
}
}
/** Userの定義 */
@AClassMapping(tableName="user")
@AClassExtra(fieldPrefix="USR_")
public static class User {
int id;
String name;
String phone;
@AGetterMapping(databaseGenerated = true, columnName="F_ID")
public int getId() { return id; }
@ASetterMapping(columnName="F_ID")
public void setId(int value) { id = value; }
public String getName() { return name; }
public void setName(String value) { name = value; }
public String getPhone() { return phone; }
public void setPhone(String value) { phone = value; }
@Override public String toString() {
return "id:" + id + ", name:" + name + ", phone:" + phone;
}
}
/** コネクションの取得 */
private static Connection getConnection() throws SQLException {
return DriverManager.getConnection(
"jdbc:hsqldb:file:testdb", "sa", ""
);
}
}