Locked History Actions

Butterfly_Persistence/ModifyField

マッピング対象のフィールド名に細工する方法

デフォルトのオートマッピングでは、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", ""
    );
  }
}