今回、SqlMapの時と同じようにユーティリティクラスを定義してみます。
以下、ソースです。
ここに出てこないソースなどは、以下の記事を参照してみてください。
[DAO実行用インターフェース]
// vim:set ts=4 sw=4 et ws is nowrap ft=java: package gsf.interfaces.dao; import gsf.interfaces.*; import com.ibatis.dao.client.*; /** * iBatis Daoオブジェクトの実行のシンタックスを定義しているインターフェースです.<br/> * このインターフェースを実装したクラスは、特定のDaoオブジェクトを受け取り、そのDao内の各メソッドを<br/> * 適切な順序で実行することを担当します(テンプレートメソッド, ファサード).<br/> * どのDaoのどのメソッドを順に実行していくかは、各実装によります.<br/> * * @author gsf_zero1 * * @see gsf.interfaces.Executor * */ public interface DaoExecutor extends Executor{ /** * 実行する.<br/> * * @return 実行結果 * * @throws DaoExecuteFailureRuntimeException Dao実行中にエラーが発生した場合 * */ Object execute(); }
[各例外クラス(実行時例外)]
// vim:set ts=4 sw=4 et ws is nowrap ft=java: package gsf.exception; /** * Dao関連でエラーが発生した場合に発生する実行時例外クラス.<br/> * * @author gsf_zero1 * */ public class DaoExecuteFailureRuntimeException extends RuntimeException{ /** * コンストラクタ.<br/> * */ public DaoExecuteFailureRuntimeException(){ super(); } /** * コンストラクタ.<br/> * * @param message メッセージ * */ public DaoExecuteFailureRuntimeException(String message){ super(message); } /** * コンストラクタ.<br/> * * @param cause 元原因例外オブジェクト * */ public DaoExecuteFailureRuntimeException(Throwable cause){ super(cause); } /** * コンストラクタ.<br/> * * @param message メッセージ * @param cause 元原因例外オブジェクト * */ public DaoExecuteFailureRuntimeException(String message, Throwable cause){ super(message, cause); } } // vim:set ts=4 sw=4 et ws is nowrap ft=java: package gsf.exception; /** * DaoManagerの生成に失敗した場合に発生する実行時例外クラス.<br/> * * @author gsf_zero1 * */ public class DaoManagerInitializeFailureRuntimeException extends RuntimeException{ /** * コンストラクタ.<br/> * */ public DaoManagerInitializeFailureRuntimeException(){ super(); } /** * コンストラクタ.<br/> * * @param message メッセージ * */ public DaoManagerInitializeFailureRuntimeException(String message){ super(message); } /** * コンストラクタ.<br/> * * @param cause 元原因例外オブジェクト * */ public DaoManagerInitializeFailureRuntimeException(Throwable cause){ super(cause); } /** * コンストラクタ.<br/> * * @param message メッセージ * @param cause 元原因例外オブジェクト * */ public DaoManagerInitializeFailureRuntimeException(String message, Throwable cause){ super(message, cause); } }
[ユーティティクラス]
// vim:set ts=4 sw=4 et ws is nowrap ft=java: package gsf.utils.dao; import java.lang.reflect.*; import java.io.*; import java.util.*; import gsf.interfaces.dao.*; import gsf.exception.*; import gsf.utils.sqlmap.SqlMapExecuteMode; import static gsf.utils.sqlmap.SqlMapExecuteMode.NO_TRANSACTION; import static gsf.utils.sqlmap.SqlMapExecuteMode.WITH_TRANSACTION; import static gsf.utils.sqlmap.SqlMapExecuteMode.BATCH_EXECUTE; import org.apache.commons.lang.*; import com.ibatis.common.resources.*; import com.ibatis.dao.client.*; import com.ibatis.dao.client.template.*; /** * iBatis Data Access Objectフレームワークのユーティリティクラスです.<br/> * DaoManager取得の為のショートカットメソッドなどを備えています.<br/> * * @author gsf_zero1 * */ public class DaoManagerUtils{ /** DaoManagerのプール */ protected static Map<String, DaoManager> POOL_DAO_MANAGER = new HashMap<String, DaoManager>(); /** デフォルトのDaoManager設定ファイル */ protected static final String DAO_CONFIG_DEFAULT = "DaoManagerConfig.xml"; /** * DaoManagerオブジェクトをプールから取得します.<br/> * プールに存在しない場合、新規に作成しそれをプーリングしてから返します.<br/> * * @param resource DaoManager設定ファイルへのリソースパス * * @return DaoManagerオブジェクト * * @throws DaoManagerInitializeFailureRuntimeException DaoManagerの生成に失敗した場合 * */ protected static DaoManager getDaoManagerFromPool(String resource){ DaoManager daoManager = POOL_DAO_MANAGER.get(resource); if(daoManager == null){ try{ daoManager = DaoManagerBuilder.buildDaoManager(Resources.getResourceAsReader(resource)); }catch(IOException ex){ throw new DaoManagerInitializeFailureRuntimeException(ex); } POOL_DAO_MANAGER.put(resource, daoManager); } return daoManager; } /** * デフォルトの設定ファイル(DaoManagerConfig.xml)を使用してDaoManagerオブジェクトを取得します.<br/> * * @return DaoManagerオブジェクト * * @throws DaoManagerInitializeFailureRuntimeException DaoManagerの生成に失敗した場合 * */ public static DaoManager getDaoManager(){ return getDaoManagerFromPool(DAO_CONFIG_DEFAULT); } /** * 指定された設定ファイルを使用してDaoManagerオブジェクトを取得します.<br/> * * @return DaoManagerオブジェクト * * @throws DaoManagerInitializeFailureRuntimeException DaoManagerの生成に失敗した場合 * */ public static DaoManager getDaoManager(String resource){ return getDaoManagerFromPool(resource); } /** * 第一引数で渡されたDaoExecutorの実装オブジェクトと、第二引数で渡されたマップを用いて<br/> * 本クラスのexecuteメソッドをトランザクション無しモードで実行するショートカットメソッドです。<br/> * 詳細は、本クラスのexecuteメソッドの説明を参照してください。<br/> * * @param executor DaoExecutorインターフェースの実装 * @param daoInterfacesMap キーがセット対象のプロパティ名で、値がDAOインターフェースのマップ. * * @return DaoExecutorオブジェクトのexecute()メソッド実行後の戻り値. * * @throws DaoExecuteFailureRuntimeException メソッド実行中にエラーが発生した場合. * * @see gsf.interfaces.dao.DaoExecutor * @see gsf.utils.dao.DaoManagerUtils#execute(com.ibatis.dao.client.DaoManager, gsf.interfaces.dao.DaoExecutor, java.util.Map, gsf.utils.sqlmap.SqlMapExecuteMode) * */ public static Object executeNoTransaction(DaoExecutor executor, Map<String, Class> daoInterfacesMap){ return execute(getDaoManager(), executor, daoInterfacesMap, NO_TRANSACTION); } /** * 指定されたDaoManagerを利用し、第ニ引数で渡されたDaoExecutorの実装オブジェクトと、第三引数で渡されたマップを用いて<br/> * 本クラスのexecuteメソッドをトランザクション無しモードで実行するショートカットメソッドです。<br/> * 詳細は、本クラスのexecuteメソッドの説明を参照してください。<br/> * * @param daoManager DaoManagerオブジェクト * @param executor DaoExecutorインターフェースの実装 * @param daoInterfacesMap キーがセット対象のプロパティ名で、値がDAOインターフェースのマップ. * * @return DaoExecutorオブジェクトのexecute()メソッド実行後の戻り値. * * @throws DaoExecuteFailureRuntimeException メソッド実行中にエラーが発生した場合. * * @see gsf.interfaces.dao.DaoExecutor * @see gsf.utils.dao.DaoManagerUtils#execute(com.ibatis.dao.client.DaoManager, gsf.interfaces.dao.DaoExecutor, java.util.Map, gsf.utils.sqlmap.SqlMapExecuteMode) * */ public static Object executeNoTransaction(DaoManager daoManager, DaoExecutor executor, Map<String, Class> daoInterfacesMap){ return execute(daoManager, executor, daoInterfacesMap, NO_TRANSACTION); } /** * 第一引数で渡されたDaoExecutorの実装オブジェクトと、第二引数で渡されたマップを用いて<br/> * 本クラスのexecuteメソッドをトランザクション無しモードで実行するショートカットメソッドです。<br/> * 詳細は、本クラスのexecuteメソッドの説明を参照してください。<br/> * * @param executor DaoExecutorインターフェースの実装 * @param daoInterfacesMap キーがセット対象のプロパティ名で、値がDAOインターフェースのマップ. * * @return DaoExecutorオブジェクトのexecute()メソッド実行後の戻り値. * * @throws DaoExecuteFailureRuntimeException メソッド実行中にエラーが発生した場合. * * @see gsf.interfaces.dao.DaoExecutor * @see gsf.utils.dao.DaoManagerUtils#execute(com.ibatis.dao.client.DaoManager, gsf.interfaces.dao.DaoExecutor, java.util.Map, gsf.utils.sqlmap.SqlMapExecuteMode) * */ public static Object executeWithTransaction(DaoExecutor executor, Map<String, Class> daoInterfacesMap){ return execute(getDaoManager(), executor, daoInterfacesMap, WITH_TRANSACTION); } /** * 指定されたDaoManagerを利用し、第ニ引数で渡されたDaoExecutorの実装オブジェクトと、第三引数で渡されたマップを用いて<br/> * 本クラスのexecuteメソッドをトランザクション無しモードで実行するショートカットメソッドです。<br/> * 詳細は、本クラスのexecuteメソッドの説明を参照してください。<br/> * * @param daoManager DaoManagerオブジェクト * @param executor DaoExecutorインターフェースの実装 * @param daoInterfacesMap キーがセット対象のプロパティ名で、値がDAOインターフェースのマップ. * * @return DaoExecutorオブジェクトのexecute()メソッド実行後の戻り値. * * @throws DaoExecuteFailureRuntimeException メソッド実行中にエラーが発生した場合. * * @see gsf.interfaces.dao.DaoExecutor * @see gsf.utils.dao.DaoManagerUtils#execute(com.ibatis.dao.client.DaoManager, gsf.interfaces.dao.DaoExecutor, java.util.Map, gsf.utils.sqlmap.SqlMapExecuteMode) * */ public static Object executeWithTransaction(DaoManager daoManager, DaoExecutor executor, Map<String, Class> daoInterfacesMap){ return execute(daoManager, executor, daoInterfacesMap, WITH_TRANSACTION); } /** * 指定されたDaoManagerからDAO具象オブジェクトを取得し、それをDaoExecutorにセットした後、DaoExecutor#execute()メソッドをコールします。 * その際、指定されたSqlMapExecuteModeの値にしたがって、トランザクション制御を行います.<br/> * <br/> * <p> * DaoExecutorにセットされるDAOは、引数daoInterfacesMapのキー名を対象プロパティとし、<br/> * そこから、セッターメソッド名を生成して、DaoManagerから取得したDAO具象オブジェクトを<br/> * セットします.<br/> * 該当するDAO具象クラスに定義するセッターメソッドは、以下の規則を守る必要があります.<br/> * <b> * <ol> * <li>メソッド名の命名規則はsetXXXXXXX.</li> * <li>メソッドの引数は、DAOインターフェース一つである必要がある.</li> * <li>メソッドの返り値の型は、void.</li> * <li>メソッドのスコープは(public, protected, private, デフォルト)の全て自由.</li> * </ol> * つまり、通常のセッターメソッドであれば問題ないという事になります.<br/> * <br/> * (例:<br/> * public void setTestTableDao(TestTableDao dao)の場合は、<br/> * マップにdaoInterfacesMap.put("testTableDao", TestTableDao.class)<br/> * と設定します.)<br/> * </b> * </p> * なお、gsf.utils.sqlmap.SqlMapUtilsと違い、こちらは、バッチモードをサポートしません。<br/> * バッチ処理が必要な場合は、各DAO内にて、startBatch,executeBatchメソッドを使用してください。<br/> * <br/> * メソッドの実行中にエラーが発生した場合、DaoExecuteFailureRuntimeException(実行時例外)がスローされます.<br/> * <br/> * また、メソッドの戻り値はDaoExecutor#execute()メソッドの戻り値をそのままObject型として返却します。<br/> * キャストして特定の型に変換してください.<br/> * <br/> * このメソッドは、トランザクションモードが指定されている場合、メソッドの実行が成功した場合は、<br/> * コミットを、失敗した場合は、ロールバックを行います。<br/> * * @param daoManager DaoManagerオブジェクト * @param executor DaoExecutorオブジェクト * @param daoInterfacesMap キーがセット対象のプロパティ名で、値がDAOインターフェースのマップ. * @param mode 実行モード * * @return メソッド実行後の戻り値. * * @throws IllegalArgumentException SqlMapExecuteModeにバッチモードが指定されている場合 * @throws DaoExecuteFailureRuntimeException メソッド実行中にエラーが発生した場合. * * @see gsf.interfaces.dao.DaoExecutor * @see gsf.utils.sqlmap.SqlMapExecuteMode * */ public static Object execute(DaoManager daoManager, DaoExecutor executor, Map<String, Class> daoInterfacesMap, SqlMapExecuteMode mode){ Object result = null; try{ if(mode == BATCH_EXECUTE){ throw new IllegalArgumentException("バッチモードはサポートしていません。DAO内にて個別にバッチ処理をおこなってください."); } for(Map.Entry<String, Class> entry : daoInterfacesMap.entrySet()){ String methodName = String.format("set%s", StringUtils.capitalize(entry.getKey())); Method targetMethod = executor.getClass().getDeclaredMethod(methodName, new Class{entry.getValue()}); targetMethod.setAccessible(true); targetMethod.invoke(executor, new Object{daoManager.getDao(entry.getValue())}); } if(mode == NO_TRANSACTION){ result = executor.execute(); }else if(mode == WITH_TRANSACTION){ try{ daoManager.startTransaction(); result = executor.execute(); daoManager.commitTransaction(); }finally{ daoManager.endTransaction(); } } }catch(InvocationTargetException ex){ throw new DaoExecuteFailureRuntimeException("メソッド実行中にエラー.", ex); }catch(IllegalAccessException ex){ throw new DaoExecuteFailureRuntimeException("メソッドへのアクセスが不正です.", ex); }catch(NoSuchMethodException ex){ throw new DaoExecuteFailureRuntimeException("該当するsetterメソッドが見つかりません.", ex); }catch(DaoException ex){ throw new DaoExecuteFailureRuntimeException(ex); } return result; } }
次は、前回作成したDAOの動作確認クラスを上記の
ユーティリティクラスを使用した版で書き直してみます。