/* * Copyright 2004-2015 the Seasar Foundation and the Others. * * 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 org.seasar.extension.jdbc.query; import java.sql.CallableStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.List; import javax.persistence.TemporalType; import org.seasar.extension.jdbc.FunctionCall; import org.seasar.extension.jdbc.JdbcContext; import org.seasar.extension.jdbc.ParamType; import org.seasar.extension.jdbc.ValueType; import org.seasar.extension.jdbc.manager.JdbcManagerImplementor; import org.seasar.framework.exception.SQLRuntimeException; import org.seasar.framework.util.PreparedStatementUtil; /** * ファンクションを呼び出す抽象クラスです。 * * @author koichik * @param <T> * ファンクションの戻り値の型。戻り値が結果セットの場合は<code>List</code>の要素の型 * @param <S> * <code>FunctionCall</code>のサブタイプです。 */ public abstract class AbstractFunctionCall<T, S extends FunctionCall<T, S>> extends AbstractModuleCall<S> implements FunctionCall<T, S> { /** 戻り値のクラス */ protected Class<T> resultClass; /** 戻り値型がLOBなら<code>true</code> */ protected boolean resultLob; /** 戻り値が<code>List</code>なら<code>true</code> */ protected boolean resultList; /** 戻り値の時制の種別 */ protected TemporalType resultTemporalType; /** * インスタンスを構築します。 * * @param jdbcManager * 内部的なJDBCマネージャ * @param resultClass * 戻り値のクラス */ public AbstractFunctionCall(final JdbcManagerImplementor jdbcManager, final Class<T> resultClass) { super(jdbcManager, true); this.resultClass = resultClass; } @SuppressWarnings("unchecked") public S lob() { resultLob = true; return (S) this; } @SuppressWarnings("unchecked") public S temporal(TemporalType temporalType) { this.resultTemporalType = temporalType; return (S) this; } public T getSingleResult() { resultList = false; prepare("getSingleResult"); logSql(); try { return getSingleResultInternal(); } finally { completed(); } } public List<T> getResultList() { resultList = true; prepare("getResultList"); logSql(); try { return getResultListInternal(); } finally { completed(); } } /** * ストアドファンクションを呼び出し、その戻り値を返します。 * * @return ストアドファンクションの戻り値 */ protected T getSingleResultInternal() { final JdbcContext jdbcContext = jdbcManager.getJdbcContext(); try { final CallableStatement cs = getCallableStatement(jdbcContext); final boolean resultSetGettable = PreparedStatementUtil.execute(cs); handleNonParamResultSets(cs, resultSetGettable); final T result = handleSingleResult(cs); handleOutParams(cs); return result; } finally { if (!jdbcContext.isTransactional()) { jdbcContext.destroy(); } completed(); } } /** * 結果セットを返すストアドファンクションを呼び出し、その戻り値を返します。 * * @return ストアドファンクションの戻り値 */ protected List<T> getResultListInternal() { final JdbcContext jdbcContext = jdbcManager.getJdbcContext(); try { final CallableStatement cs = getCallableStatement(jdbcContext); final boolean resultSetGettable = PreparedStatementUtil.execute(cs); handleNonParamResultSets(cs, resultSetGettable); final List<T> result = handleResultList(cs); handleOutParams(cs); return result; } finally { if (!jdbcContext.isTransactional()) { jdbcContext.destroy(); } } } /** * ストアドファンクションの戻り値を受け取る<code>OUT</code>パラメータを準備します。 */ protected void prepareReturnParameter() { final ValueType valueType = getValueType(resultList ? List.class : resultClass, resultLob, resultTemporalType); final Param p = addParam(null, resultClass, valueType); p.paramType = ParamType.OUT; } /** * ストアドファンクションの戻り値を処理して、結果を返します。 * * @param cs * 呼び出し可能なステートメント * @return ストアドファンクションの戻り値を処理した結果 */ @SuppressWarnings("unchecked") protected T handleSingleResult(final CallableStatement cs) { try { final Param param = getParam(0); return (T) param.valueType.getValue(cs, 1); } catch (final SQLException e) { throw new SQLRuntimeException(e); } } /** * ストアドファンクションの戻り値を処理して、結果のリストを返します。 * * @param cs * 呼び出し可能なステートメント * @return ストアドファンクションの戻り値を処理した結果のリスト */ @SuppressWarnings("unchecked") protected List<T> handleResultList(final CallableStatement cs) { try { final Param param = getParam(0); final ResultSet rs = ResultSet.class.cast(param.valueType.getValue( cs, 1)); return (List<T>) handleResultList(resultClass, rs); } catch (final SQLException e) { throw new SQLRuntimeException(e); } } }