いろいろ備忘録日記

主に .NET と Python絡みのメモを公開しています。

iBatis奮闘記-0009 (RowHandlerの使用)

iBatisでは、行データをハンドリングするハンドラを
指定することができます。

com.ibatis.sqlmap.event.RowHandler

RowHandlerはインターフェースとなっており、

void handleRow(Object obj);

というメソッドが一つだけ定義されています。
このメソッドに渡ってくる引数が行データです。

ハンドラ付きでsqlMapを実行するには、SqlMapClientの以下のメソッドを
使用します。

void queryWithRowHandler(String, Object, RowHandler);

RowHandlerの実装クラスを作成するのは簡単なのですが、
問題は、このメソッドの返り値がvoidとなっている点です。
結果を受け取りたい場合は、ハンドラ内で値を保持して返す必要があります。

今回は、行データをロギングしながら、リストに保持するハンドラを作成してみます。
一つのハンドラで作成してもよかったのですが、面白くないので責任毎にクラスを
分けてみました。

以下サンプルです。

[ロギングを担当するRowHanler]

// vim:set ts=4 sw=4 et ws is nowrap ft=java:
package gsf.samples.ibatis.sample007;

import com.ibatis.sqlmap.client.event.*;

import org.apache.commons.logging.*;

/**
 * 行データをロギングしていくRowHandlerの実装クラス.<br/>
 *
 * @author gsf_zero1
 *
 * @see com.ibatis.sqlmap.client.event.RowHandler
 *
 */
public class LoggingRowHandler implements RowHandler{

    /** ログオブジェクト */
    private static final Log log = LogFactory.getLog(LoggingRowHandler.class);

    /**
     * コンストラクタ.<br/>
     *
     */
    public LoggingRowHandler(){
        // nop;
    }

    /**
     * 行をハンドリングする.<br/>
     * このメソッドは、引数で指定された<br/>
     * 行データをログ出力します.<br/>
     *
     * @param row 行データ
     *
     * @see com.ibatis.sqlmap.client.event.RowHandler#handleRow(java.lang.Object)
     *
     */
    public void handleRow(Object row){

        log.info(row);

    }

}

[行データの保持を担当するRowHandler]

// vim:set ts=4 sw=4 et ws is nowrap ft=java:
package gsf.samples.ibatis.sample007;

import java.util.*;

import com.ibatis.sqlmap.client.event.*;

/**
 * 行データを内部でリストとして保持するRowHandlerの実装クラス.<br/>
 *
 * @author gsf_zero1
 *
 * @see com.ibatis.sqlmap.client.event.RowHandler
 *
 */
public class ListStoredRowHandler<T> implements RowHandler{

    /** 行データのリスト */
    private List<T> rowList;

    /**
     * コンストラクタ.<br/>
     *
     */
    public ListStoredRowHandler(){
        this.rowList = new ArrayList<T>();
    }

    /**
     * 行データをハンドリングする.<br/>
     * このメソッドは、引数で渡された行データを<br/>
     * 内部のリストに保持していきます.<br/>
     *
     * @param row 行データ
     *
     * @see com.ibatis.sqlmap.client.event.RowHandler#handleRow(java.lang.Object)
     *
     */
    public void handleRow(Object row){
        this.rowList.add((T) row);
    }

    /**
     * 行データを取得する.<br/>
     *
     * @return 行データのリスト
     *
     */
    public List<T> getRowList(){
        return this.rowList;
    }

}

[複数のRowHandlerの実行を担当するRowHandler]

// vim:set ts=4 sw=4 et ws is nowrap ft=java:
package gsf.samples.ibatis.sample007;

import java.util.*;

import com.ibatis.sqlmap.client.event.*;

/**
 * 複数のRowHandlerをチェーンして実行するRowHandlerの実装クラス.<br/>
 *
 * @author gsf_zero1
 *
 * @see com.ibatis.sqlmap.client.event.RowHandler
 *
 */
public class ChainedRowHandler implements RowHandler{

    /** 内部で保持しているハンドラのリスト */
    private List<RowHandler> handlers;

    /**
     * コンストラクタ.<br/>
     *
     */
    public ChainedRowHandler(){
        this.handlers = new ArrayList<RowHandler>();
    }

    /**
     * ハンドラを追加する.<br/>
     *
     * @param handler ハンドラ
     *
     */
    public void addRowHandler(RowHandler handler){
        this.handlers.add(handler);
    }

    /**
     * 行データをハンドリングする.<br/>
     * このメソッドは、内部で保持しているハンドラのリスト<br/>
     * からハンドラを取り出し、順にhandleRowメソッドをコール<br/>
     * していきます.<br/>
     *
     * @param row 行データ
     *
     * @see com.ibatis.sqlmap.client.event.RowHandler#handleRow(java.lang.Object)
     *
     */
    public void handleRow(Object row){
        for(RowHandler aHandler : this.handlers){
            aHandler.handleRow(row);
        }
    }
}

[SqlMapの実行を担当するクラス]

// vim:set ts=4 sw=4 et ws is nowrap ft=java:
package gsf.samples.ibatis.sample007;

import java.sql.*;

import gsf.interfaces.sqlmap.*;

import com.ibatis.sqlmap.client.*;

/**
 * Sample007にて、SqlMapの実行を担当するクラス.<br/>
 *
 * @author gsf_zero1
 *
 * @see gsf.interfaces.sqlmap.SqlMapClientExecutor
 *
 */
public class Sample007SqlMapClientExecutor implements SqlMapClientExecutor{

    /**
     * SqlMapを実行する.<br/>
     *
     * @param sqlMap SqlMapClientオブジェクト
     * 
     * @return 結果
     *
     * @throws SQLException SQL処理実行中にエラーが発生した場合
     *
     * @see gsf.interfaces.sqlmap.SqlMapClientExecutor#execute(com.ibatis.sqlmap.client.SqlMapClient)
     *
     */
    public Object execute(SqlMapClient sqlMap) throws SQLException{

        ChainedRowHandler    chainedHandler    = new ChainedRowHandler();
        LoggingRowHandler    loggingHandler    = new LoggingRowHandler();

        ListStoredRowHandler<Sample007TestTable> listStoredHandler = new ListStoredRowHandler<Sample007TestTable>();

        chainedHandler.addRowHandler(loggingHandler);
        chainedHandler.addRowHandler(listStoredHandler);

        sqlMap.queryWithRowHandler("sample007FindAll", null, chainedHandler);

        return listStoredHandler.getRowList();

    }

}

[データクラス]

// vim:set ts=4 sw=4 et ws is nowrap ft=java:
package gsf.samples.ibatis.sample007;

import java.io.*;
import java.util.Date;
import java.sql.*;

import org.apache.commons.lang.builder.*;

/**
 * SAMPLE007_TEST_TABLEに対応するドメインクラス.<br/>
 *
 * @author gsf_zero1
 *
 */
public class Sample007TestTable implements Serializable{

    /** ID */
    private Integer   id;

    /** DATA1 */
    private Integer   data1;
    
    /** DATA2 */
    private String    data2;

    /** DATA3 */
    private Date      data3;

    /** DATA4 */
    private Timestamp data4;

    /**
     * コンストラクタ.<br/>
     *
     */
    public Sample007TestTable(){
        // nop;
    }
    
    /**
     * Get id.
     *
     * @return id as Integer.
     */
    public Integer getId(){
        return this.id;
    }
    
    /**
     * Set id.
     *
     * @param id the value to set.
     */
    public void setId(Integer id){
        this.id = id;
    }
    
    /**
     * Get data1.
     *
     * @return data1 as Integer.
     */
    public Integer getData1(){
        return this.data1;
    }
    
    /**
     * Set data1.
     *
     * @param data1 the value to set.
     */
    public void setData1(Integer data1){
        this.data1 = data1;
    }
    
    /**
     * Get data2.
     *
     * @return data2 as String.
     */
    public String getData2(){
        return this.data2;
    }
    
    /**
     * Set data2.
     *
     * @param data2 the value to set.
     */
    public void setData2(String data2){
        this.data2 = data2;
    }
    
    /**
     * Get data3.
     *
     * @return data3 as Date.
     */
    public Date getData3(){
        return this.data3;
    }
    
    /**
     * Set data3.
     *
     * @param data3 the value to set.
     */
    public void setData3(Date data3){
        this.data3 = data3;
    }
    
    /**
     * Get data4.
     *
     * @return data4 as Timestamp.
     */
    public Timestamp getData4(){
        return this.data4;
    }
    
    /**
     * Set data4.
     *
     * @param data4 the value to set.
     */
    public void setData4(Timestamp data4){
        this.data4 = data4;
    }

    /**
     * オブジェクトの文字列表現を返す.<br/>
     *
     * @return 文字列表現
     *
     */
    @Override
    public String toString(){
        return new ReflectionToStringBuilder(this).toString();
    }

}

[動作確認クラス]

// vim:set ts=4 sw=4 et ws is nowrap ft=java:
package gsf.samples.ibatis.sample007;

import java.util.*;

import gsf.utils.sqlmap.*;

/**
 * iBatis Sample 007の動作確認用のクラス.<br/>
 *
 * @author gsf_zero1
 *
 */
public class IBatisSample007{

    /**
     * アプリケーションエントリポイント.<br/>
     *
     * @param args 起動時引数.
     *
     */
    public static void main(String[] args){

        List<Sample007TestTable> result 
            = (List<Sample007TestTable>) SqlMapUtils.executeNoTransaction(
                                            new Sample007SqlMapClientExecutor(), 
                                            "execute");

        System.out.println("\n\n");

        for(Sample007TestTable obj : result){
            System.out.println(obj);
        }

    }

}

[SqlMap設定ファイル]

<?xml version="1.0" encoding="Windows-31J"?>
<!-- vim:set ts=4 sw=4 et ws is nowrap ft=xml: -->
<!DOCTYPE sqlMap 
          PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" 
          "http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMap namespace="RowHandler">

    <typeAlias alias="Sample007TestTable" type="gsf.samples.ibatis.sample007.Sample007TestTable"/>

    <select id="sample007FindAll" resultClass="Sample007TestTable">
        select
             id
            ,data1
            ,data2
            ,data3
            ,data4
        from
            SAMPLE007_TEST_TABLE
        order by
            id
    </select>

</sqlMap>

てな感じです。