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}