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.simple;
018
019import java.util.Arrays;
020import java.util.LinkedHashSet;
021import java.util.Map;
022import javax.sql.DataSource;
023
024import org.springframework.jdbc.core.JdbcTemplate;
025import org.springframework.jdbc.core.RowMapper;
026import org.springframework.jdbc.core.SqlParameter;
027import org.springframework.jdbc.core.namedparam.SqlParameterSource;
028
029/**
030 * A SimpleJdbcCall is a multi-threaded, reusable object representing a call
031 * to a stored procedure or a stored function. It provides meta-data processing
032 * to simplify the code needed to access basic stored procedures/functions.
033 * All you need to provide is the name of the procedure/function and a Map
034 * containing the parameters when you execute the call. The names of the
035 * supplied parameters will be matched up with in and out parameters declared
036 * when the stored procedure was created.
037 *
038 * <p>The meta-data processing is based on the DatabaseMetaData provided by
039 * the JDBC driver. Since we rely on the JDBC driver, this "auto-detection"
040 * can only be used for databases that are known to provide accurate meta-data.
041 * These currently include Derby, MySQL, Microsoft SQL Server, Oracle, DB2,
042 * Sybase and PostgreSQL. For any other databases you are required to declare
043 * all parameters explicitly. You can of course declare all parameters
044 * explicitly even if the database provides the necessary meta-data. In that
045 * case your declared parameters will take precedence. You can also turn off
046 * any meta-data processing if you want to use parameter names that do not
047 * match what is declared during the stored procedure compilation.
048 *
049 * <p>The actual insert is being handled using Spring's {@link JdbcTemplate}.
050 *
051 * <p>Many of the configuration methods return the current instance of the
052 * SimpleJdbcCall in order to provide the ability to chain multiple ones
053 * together in a "fluent" interface style.
054 *
055 * @author Thomas Risberg
056 * @author Stephane Nicoll
057 * @since 2.5
058 * @see java.sql.DatabaseMetaData
059 * @see org.springframework.jdbc.core.JdbcTemplate
060 */
061public class SimpleJdbcCall extends AbstractJdbcCall implements SimpleJdbcCallOperations {
062
063        /**
064         * Constructor that takes one parameter with the JDBC DataSource to use when
065         * creating the underlying JdbcTemplate.
066         * @param dataSource the {@code DataSource} to use
067         * @see org.springframework.jdbc.core.JdbcTemplate#setDataSource
068         */
069        public SimpleJdbcCall(DataSource dataSource) {
070                super(dataSource);
071        }
072
073        /**
074         * Alternative Constructor that takes one parameter with the JdbcTemplate to be used.
075         * @param jdbcTemplate the {@code JdbcTemplate} to use
076         * @see org.springframework.jdbc.core.JdbcTemplate#setDataSource
077         */
078        public SimpleJdbcCall(JdbcTemplate jdbcTemplate) {
079                super(jdbcTemplate);
080        }
081
082
083        @Override
084        public SimpleJdbcCall withProcedureName(String procedureName) {
085                setProcedureName(procedureName);
086                setFunction(false);
087                return this;
088        }
089
090        @Override
091        public SimpleJdbcCall withFunctionName(String functionName) {
092                setProcedureName(functionName);
093                setFunction(true);
094                return this;
095        }
096
097        @Override
098        public SimpleJdbcCall withSchemaName(String schemaName) {
099                setSchemaName(schemaName);
100                return this;
101        }
102
103        @Override
104        public SimpleJdbcCall withCatalogName(String catalogName) {
105                setCatalogName(catalogName);
106                return this;
107        }
108
109        @Override
110        public SimpleJdbcCall withReturnValue() {
111                setReturnValueRequired(true);
112                return this;
113        }
114
115        @Override
116        public SimpleJdbcCall declareParameters(SqlParameter... sqlParameters) {
117                for (SqlParameter sqlParameter : sqlParameters) {
118                        if (sqlParameter != null) {
119                                addDeclaredParameter(sqlParameter);
120                        }
121                }
122                return this;
123        }
124
125        @Override
126        public SimpleJdbcCall useInParameterNames(String... inParameterNames) {
127                setInParameterNames(new LinkedHashSet<String>(Arrays.asList(inParameterNames)));
128                return this;
129        }
130
131        @Override
132        public SimpleJdbcCall returningResultSet(String parameterName, RowMapper<?> rowMapper) {
133                addDeclaredRowMapper(parameterName, rowMapper);
134                return this;
135        }
136
137        @Override
138        public SimpleJdbcCall withoutProcedureColumnMetaDataAccess() {
139                setAccessCallParameterMetaData(false);
140                return this;
141        }
142
143        @Override
144        public SimpleJdbcCall withNamedBinding() {
145                setNamedBinding(true);
146                return this;
147        }
148
149        @Override
150        @SuppressWarnings("unchecked")
151        public <T> T executeFunction(Class<T> returnType, Object... args) {
152                return (T) doExecute(args).get(getScalarOutParameterName());
153        }
154
155        @Override
156        @SuppressWarnings("unchecked")
157        public <T> T executeFunction(Class<T> returnType, Map<String, ?> args) {
158                return (T) doExecute(args).get(getScalarOutParameterName());
159        }
160
161        @Override
162        @SuppressWarnings("unchecked")
163        public <T> T executeFunction(Class<T> returnType, SqlParameterSource args) {
164                return (T) doExecute(args).get(getScalarOutParameterName());
165        }
166
167        @Override
168        @SuppressWarnings("unchecked")
169        public <T> T executeObject(Class<T> returnType, Object... args) {
170                return (T) doExecute(args).get(getScalarOutParameterName());
171        }
172
173        @Override
174        @SuppressWarnings("unchecked")
175        public <T> T executeObject(Class<T> returnType, Map<String, ?> args) {
176                return (T) doExecute(args).get(getScalarOutParameterName());
177        }
178
179        @Override
180        @SuppressWarnings("unchecked")
181        public <T> T executeObject(Class<T> returnType, SqlParameterSource args) {
182                return (T) doExecute(args).get(getScalarOutParameterName());
183        }
184
185        @Override
186        public Map<String, Object> execute(Object... args) {
187                return doExecute(args);
188        }
189
190        @Override
191        public Map<String, Object> execute(Map<String, ?> args) {
192                return doExecute(args);
193        }
194
195        @Override
196        public Map<String, Object> execute(SqlParameterSource parameterSource) {
197                return doExecute(parameterSource);
198        }
199
200}