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}