001/*
002 * Copyright 2014 The Apache Software Foundation.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.apache.commons.dbutils;
018
019import java.sql.CallableStatement;
020import java.sql.SQLException;
021
022/**
023 * Represents an OUT parameter for a stored procedure.  When running a stored
024 * procedure with {@link QueryRunner}, pass an instance of
025 * <code>OutParameter</code> to indicate that the parameter at that index is an
026 * OUT parameter.  The value of the parameter may be obtained from the
027 * <code>OutParameter</code> instance via {@link #getValue() }.
028 * <p>
029 * INOUT parameters are also supported by setting the <code>value</code> of
030 * the <code>OutParameter</code> instance before invoking the stored procedure.
031 *
032 * @param <T> the class of the parameter; should be compatible via cast with the
033 * class returned by the <code>CallableStatement.getObject(int)</code> method.
034 */
035public class OutParameter<T> {
036    private final int sqlType;
037    private final Class<T> javaType;
038    private T value = null;
039
040    /**
041     * Construct an <code>OutParameter</code> for the given JDBC SQL type and
042     * Java type.
043     * @param sqlType the JDBC SQL type of the parameter as in
044     * <code>java.sql.Types</code>.
045     * @param javaType the Java class of the parameter value, cast compatible
046     * with the type returned by <code>CallableStatement.getObject(int)</code>
047     * for the JDBC type given by <code>sqlType</code>.
048     */
049    public OutParameter(int sqlType, Class<T> javaType) {
050        this.sqlType = sqlType;
051        this.javaType = javaType;
052    }
053
054    /**
055     * Construct an <code>OutParameter</code> for the given JDBC SQL type and
056     * Java type and with the given value.  The parameter will be treated as an
057     * INOUT parameter if the value is null.
058     * @param sqlType the JDBC SQL type of the parameter as in
059     * <code>java.sql.Types</code>.
060     * @param javaType the Java class of the parameter value, cast compatible
061     * with the type returned by <code>CallableStatement.getObject(int)</code>
062     * for the JDBC type given by <code>sqlType</code>.
063     * @param value the IN value of the parameter
064     */
065    public OutParameter(int sqlType, Class<T> javaType, T value) {
066        this.sqlType = sqlType;
067        this.javaType = javaType;
068        this.value = value;
069    }
070
071    /**
072     * Get the JDBC SQL type for this OUT parameter.
073     * @return the JDBC SQL type for this OUT parameter.
074     */
075    public int getSqlType() {
076        return sqlType;
077    }
078
079    /**
080     * Get the Java class for this OUT parameter.
081     * @return the Java class for this OUT parameter.
082     */
083    public Class<T> getJavaType()
084    {
085        return javaType;
086    }
087
088    /**
089     * Get the value of the OUT parameter.  After the stored procedure has
090     * been executed, the value is the value returned via this parameter.
091     * @return the value of the OUT parameter.
092     */
093    public T getValue() {
094        return value;
095    }
096
097    /**
098     * Set the value of the OUT parameter.  If the value is not null when the
099     * stored procedure is executed, then the parameter will be treated like an
100     * INOUT parameter.
101     * @param value the new value for the parameter.
102     */
103    public void setValue(T value) {
104        this.value = value;
105    }
106
107    /**
108     * Set the value using the return value of the parameter an the given index
109     * from the given <code>CallableStatement</code>.
110     * @param stmt the already executed statement
111     * @param index the (1-based) index of the parameter
112     * @throws SQLException when the value could not be retrieved from the
113     * statement.
114     */
115    void setValue(CallableStatement stmt, int index) throws SQLException {
116        Object object = stmt.getObject(index);
117        value = javaType.cast(object);
118    }
119
120    /**
121     * Set up the given statement by registering an OUT parameter at the given
122     * index using the <code>sqlType</code> and <code>value</code> of this
123     * <code>OutParameter</code>.  If the value is not null, the parameter is
124     * treated like an INOUT parameter and the value is set on the statement.
125     * @param stmt the statement the parameter should register on.
126     * @param index the (1-based) index of the parameter.
127     * @throws SQLException if the parameter could not be registered, or if the
128     * value of the parameter could not be set.
129     */
130    void register(CallableStatement stmt, int index) throws SQLException {
131        stmt.registerOutParameter(index, sqlType);
132        if (value != null) {
133            stmt.setObject(index, value);
134        }
135    }
136
137    @Override
138    public String toString()
139    {
140        return "OutParameter{" + "sqlType=" + sqlType + ", javaType="
141            + javaType + ", value=" + value + '}';
142    }
143}