主キーがLong型以外の場合の対応
DBFluteのMappingのモードは
torque.jdbcToJavaNativeMap = map:{ ;NUMERIC=$$AutoMapping$$ ;DECIMAL=$$AutoMapping$$ }
の場合
小数点桁数が1以上 | NUMERICに対応する型 | java.math.BigDecimal |
小数点桁数が0でサイズが10桁以上 | BIGINTに対応する型 | java.lang.Long |
小数点桁数が0でサイズが9桁以下 | INTEGERに対応する型 | java.lang.Integer |
になる。AutoMappingがない場合はjava.math.BigDecimalにマッピングされる。
主キーがAutoMappingで10桁以上であればLongにマッピングされるのでそのままでS2BuriとDBFluteで連携できたけどそれ以外の型の場合AbstDataAccessUtilLongKeyのgetLongPkeyのところでClass Cast Exceptionになる。
protected Long getLongPkey(Object target, String prop) { BeanDesc beanDesc = BeanDescFactory.getBeanDesc(target.getClass()); PropertyDesc pkeyPropertyDesc = beanDesc.getPropertyDesc(prop); Object result = pkeyPropertyDesc.getValue(target); if(result == null) { result = new Long(0); } assert result instanceof Long; return (Long) result; }
[S2buri]主キーをStringにすると自動設定しないのね。
http://d.hatena.ne.jp/dachii/20080522#p1
をみるとExtend Attributeを設定すればLong以外でも問題ないようだ。
でも毎回この設定を書くのって面倒だし設定わすれると実行時エラーなのでつらい。
なので主キーの型をようするにLongに変換すればいいだけじゃね?ということで動くのか確認してみたところ大丈夫そうだった。
以下各に手順。
diconに登録してあるクラスだけをかきかえるだけかと思ったらnewしているのでかえられなかったので
コピーペープログラミングで対応してみた(クラス名は適当)。
buri/dicon/buri-share.dicon
をコピーしてしてコンポーネント名を変更。
BuriDataAccessFactoryImplをMyBuriDataAccessFactoryImplに変更。
MyBuriDataAccessFactoryImplはBuriDataAccessFactoryImplをextendsしてを作る。
BuriDataAccessScriptFactoryImplの中味をすべてコピー(プロパティがprivateなので拡張できないので)。
@Override public DataAccessUtil getDataAccessUtil(Class tgtClass) { String className = classDefUtil.getClassName(tgtClass); if (classToUtil.containsKey(className)) { return (DataAccessUtil) classToUtil.get(className); } BuriDataFieldType fieldType = new BuriDataFieldType(); fieldType.setId(className); fieldType = preprocessor.preprocess(fieldType); ScriptDataAccessUtilLongKeyImpl dataAccessUtil = new MyScriptDataAccessUtilKeyImpl(fieldType); dataAccessUtil.setScriptFactory(scriptFactory); classToUtil.put(className, dataAccessUtil); return dataAccessUtil; }
のみ書き換える。ScriptDataAccessUtilKeyImplをMyScriptDataAccessUtilKeyImplに。
MyScriptDataAccessUtilKeyImplでgetLongPkeyを変更。
package org.escafe.buri.dataaccess.impl; import org.apache.commons.beanutils.converters.LongConverter; import org.escafe.buri.oouo.internal.structure.BuriDataFieldType; import org.seasar.framework.beans.BeanDesc; import org.seasar.framework.beans.PropertyDesc; import org.seasar.framework.beans.factory.BeanDescFactory; public class MyScriptDataAccessUtilKeyImpl extends ScriptDataAccessUtilLongKeyImpl { public MyScriptDataAccessUtilKeyImpl(BuriDataFieldType fieldType) { super(fieldType); } static LongConverter _converter = new LongConverter(new Long(0)); @Override protected Long getLongPkey(Object target, String prop) { BeanDesc beanDesc = BeanDescFactory.getBeanDesc(target.getClass()); PropertyDesc pkeyPropertyDesc = beanDesc.getPropertyDesc(prop); Object result = pkeyPropertyDesc.getValue(target); return (Long)_converter.convert(Long.class, result); } }
主キーの型がBigDecimal, Integer, Long, Stringでも問題なく動いた。
この辺はやっぱりDBFluteは素敵だが設定値一覧のドキュメントがないので何度もはまる。
Buriのコードを直接書き換えてOracleですべてのテストがとおることは確認した。
assert result instanceof Long;
にしないといけない理由があるんだろうか?
以下パッチ。
Index: src/main/java/org/escafe/buri/util/packages/abst/AbstDataAccessUtilLongKey.java =================================================================== --- src/main/java/org/escafe/buri/util/packages/abst/AbstDataAccessUtilLongKey.java (revision 425) +++ src/main/java/org/escafe/buri/util/packages/abst/AbstDataAccessUtilLongKey.java (working copy) @@ -10,6 +10,7 @@ import java.util.List; import java.util.Map; +import org.apache.commons.beanutils.converters.LongConverter; import org.seasar.coffee.dataaccess.DataAccessUtilLongKey; import org.seasar.framework.beans.BeanDesc; import org.seasar.framework.beans.PropertyDesc; @@ -22,11 +23,8 @@ BeanDesc beanDesc = BeanDescFactory.getBeanDesc(target.getClass()); PropertyDesc pkeyPropertyDesc = beanDesc.getPropertyDesc(prop); Object result = pkeyPropertyDesc.getValue(target); - if(result == null) { - result = new Long(0); - } - assert result instanceof Long; - return (Long) result; + LongConverter converter = new LongConverter(new Long(0)); + return (Long)converter.convert(Long.class, result); } @Override