001/*
002 * Copyright 2002-2018 the original author or authors.
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 *      https://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.springframework.jdbc.core.support;
018
019import java.sql.Connection;
020import java.sql.PreparedStatement;
021import java.sql.SQLException;
022
023import org.springframework.jdbc.core.SqlTypeValue;
024import org.springframework.lang.Nullable;
025
026/**
027 * Abstract implementation of the SqlTypeValue interface, for convenient
028 * creation of type values that are supposed to be passed into the
029 * {@code PreparedStatement.setObject} method. The {@code createTypeValue}
030 * callback method has access to the underlying Connection, if that should
031 * be needed to create any database-specific objects.
032 *
033 * <p>A usage example from a StoredProcedure (compare this to the plain
034 * SqlTypeValue version in the superclass javadoc):
035 *
036 * <pre class="code">proc.declareParameter(new SqlParameter("myarray", Types.ARRAY, "NUMBERS"));
037 * ...
038 *
039 * Map&lt;String, Object&gt; in = new HashMap&lt;String, Object&gt;();
040 * in.put("myarray", new AbstractSqlTypeValue() {
041 *   public Object createTypeValue(Connection con, int sqlType, String typeName) throws SQLException {
042 *         oracle.sql.ArrayDescriptor desc = new oracle.sql.ArrayDescriptor(typeName, con);
043 *         return new oracle.sql.ARRAY(desc, con, seats);
044 *   }
045 * });
046 * Map out = execute(in);
047 * </pre>
048 *
049 * @author Juergen Hoeller
050 * @since 1.1
051 * @see java.sql.PreparedStatement#setObject(int, Object, int)
052 * @see org.springframework.jdbc.object.StoredProcedure
053 */
054public abstract class AbstractSqlTypeValue implements SqlTypeValue {
055
056        @Override
057        public final void setTypeValue(PreparedStatement ps, int paramIndex, int sqlType, @Nullable String typeName)
058                        throws SQLException {
059
060                Object value = createTypeValue(ps.getConnection(), sqlType, typeName);
061                if (sqlType == TYPE_UNKNOWN) {
062                        ps.setObject(paramIndex, value);
063                }
064                else {
065                        ps.setObject(paramIndex, value, sqlType);
066                }
067        }
068
069        /**
070         * Create the type value to be passed into {@code PreparedStatement.setObject}.
071         * @param con the JDBC Connection, if needed to create any database-specific objects
072         * @param sqlType the SQL type of the parameter we are setting
073         * @param typeName the type name of the parameter
074         * @return the type value
075         * @throws SQLException if an SQLException is encountered setting
076         * parameter values (that is, there's no need to catch SQLException)
077         * @see java.sql.PreparedStatement#setObject(int, Object, int)
078         */
079        protected abstract Object createTypeValue(Connection con, int sqlType, @Nullable String typeName)
080                        throws SQLException;
081
082}