/*
* Copyright (c) 2011 NTT DATA Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package jp.terasoluna.fw.collector.db;
import java.lang.reflect.InvocationTargetException;
import jp.terasoluna.fw.collector.LogId;
import jp.terasoluna.fw.collector.vo.DataValueObject;
import jp.terasoluna.fw.exception.SystemException;
import jp.terasoluna.fw.logger.TLogger;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
/**
* Queueing1NRelationResultHandlerImplの実装クラス<br>
* <p>
* QueueingResultHandlerImplの1:Nマッピング対応版。<br>
* 1:Nマッピング使用時、iBATISは1:N構造のオブジェクトが完成する前に ResultHandler#handleResult()に渡すため、 このコレクタでは、
* ResultHandler#handleResult()に渡された結果を、次回同メソッドが実行されたときに キューに格納する。 最後に渡された結果は、iBATISが処理を終えた時点でキューに格納する。<br>
* また、1:Nマッピング使用時、iBATISは全てのデータを取得し終わるまで、 ResultHandler#handleResult()に渡したオブジェクトを、全てiBATIS内部に保持し続けるため、
* このコレクタでは、ResultHandler#handleResult()に渡されたオブジェクトのシャローコピーをキューに格納し、
* ResultHandler#handleResult()に渡されたオブジェクトの全プロパティを初期化する。
* </p>
* <p>
* 使用上の注意:
* <ul>
* <li>resultMap要素のgroupBy属性に書かれた列を第1ソートキーとしてソート(ORDER BY)すること。<br>
* (ソートキーを誤った場合、またはソートをしない場合、 1:N構造のコレクタ結果クラスが不完全な状態でBLogicを実行してしまうので注意すること)</li>
* </ul>
* </p>
* <p>
* 使いどころ
* <ul>
* <li>コレクタ用のsqlMapでiBATISの1:Nマッピングを利用し、かつ、 データ量が多く、メモリを節約する必要があるとき<br>
* (1:Nマッピングを利用しない場合は、 オブジェクトのシャローコピーや初期化は不要であるため、 QueueingResultHandlerImplを使用すること)</li>
* </ul>
* </p>
* <p>
* sqlMap記述例1(1:Nマッピング):
*
* <pre>
* <resultMap id="rmap_JB1231_SQL" class="sample.JB1231Data" <b>groupBy="col1"</b>>
* <result property="col1"/>
* <result property="col2"/>
* <result property="col3"/>
* <result property="detail1" resultMap="rmap_JB1231_SQL_detail1"/>
* </resultMap>
* <resultMap id="rmap_JB1231_SQL_detail1" class="sample.Detail1">
* <result property="d12" column="d12"/>
* <result property="d13" column="d13"/>
* </resultMap>
* <select id="JB1231_SQL" resultMap="rmap_JB1231_SQL">
* SELECT
* t1.col1 as col1,
* t1.col2 as col2,
* t1.col3 as col3,
* d1.col2 as d12,
* d1.col3 as d13,
* FROM (sample_table1 t1
* left outer join sample_table1_detail1 d1 on t1.col1 = d1.col1)
* <b>ORDER BY col1</b>, ...
* </select>
* </pre>
*
* sqlMap記述例2(1:M:Nマッピング):
*
* <pre>
* <resultMap id="rmap_JB1231_SQL" class="sample.JB1231Data" <b>groupBy="col1"</b>>
* <result property="col1"/>
* <result property="col2"/>
* <result property="col3"/>
* <result property="detail1" resultMap="rmap_JB1231_SQL_detail1"/>
* <result property="detail2" resultMap="rmap_JB1231_SQL_detail2"/>
* </resultMap>
* <resultMap id="rmap_JB1231_SQL_detail1" class="sample.Detail1">
* <result property="d12" column="d12"/>
* <result property="d13" column="d13"/>
* </resultMap>
* <resultMap id="rmap_JB1231_SQL_detail2" class="sample.Detail2">
* <result property="d22" column="d22"/>
* <result property="d23" column="d23"/>
* </resultMap>
* <select id="JB1231_SQL" resultMap="rmap_JB1231_SQL">
* SELECT * FROM (
* SELECT
* t1.col1 as col1,
* t1.col2 as col2,
* t1.col3 as col3,
* d1.col2 as d12,
* d1.col3 as d13,
* null as d22,
* null as d23
* FROM (sample_table1 t1
* left outer join sample_table1_detail1 d1 on t1.col1 = d1.col1)
* UNION ALL
* SELECT
* t1.col1 as col1,
* t1.col2 as col2,
* t1.col3 as col3,
* null as d12,
* null as d13,
* d2.col2 as d22,
* d2.col3 as d23
* FROM (sample_table1 t1
* left outer join sample_table1_detail2 d2 on t1.col1 = d2.col1)
* ) AS A <b>ORDER BY col1</b>, ...
* </select>
* </pre>
*
* </p>
* @deprecated
* 1:Nマッピングを行なう際は、MyBatis3のselectステートメントのresultOrdered属性をtrueにすることにより、
* {@code Queueing1NRelationResultHandlerImpl}、および{@code DaoCollectorConfig#setRelation1n()}の設定が不要となる。
* @see <a href="http://mybatis.github.io/mybatis-3/ja/sqlmap-xml.html">http://mybatis.github.io/mybatis-3/ja/sqlmap-xml.html</a>
*/
@Deprecated
public class Queueing1NRelationResultHandlerImpl<T> extends
QueueingResultHandlerImpl<T> {
/**
* Log.
*/
private static final TLogger LOGGER = TLogger
.getLogger(Queueing1NRelationResultHandlerImpl.class);
/**
* 前回handleResultメソッドに渡された<code>Row</code>データをキューに格納する。
*/
@Override
public void delayCollect() {
if (this.prevRow == null) {
return;
}
if (Thread.currentThread().isInterrupted()) {
return;
}
try {
// オブジェクトのシャローコピーを作成
Object copy = BeanUtils.cloneBean(this.prevRow);
PropertyUtils.copyProperties(this.prevRow, this.prevRow
.getClass().newInstance());
if (this.daoCollector != null) {
// 取得したオブジェクトのシャローコピーを1件キューにつめる
this.daoCollector.addQueue(new DataValueObject(copy,
this.dataCount.incrementAndGet()));
}
} catch (IllegalAccessException e) {
throw new SystemException(e);
} catch (InstantiationException e) {
throw new SystemException(e);
} catch (InvocationTargetException e) {
throw new SystemException(e);
} catch (NoSuchMethodException e) {
throw new SystemException(e);
} catch (InterruptedException e) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace(LogId.TAL041002, Thread.currentThread()
.getName());
}
// InterruptedException発生によりスレッドの「割り込み状態」はクリアされる。
// 呼び出し元に割り込みが発生したことを通知する必要があるため、「割り込み状態」を再度保存する。
Thread.currentThread().interrupt();
}
}
}