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