001/*
002 * Copyright 2002-2014 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.namedparam;
018
019import java.util.Collections;
020import java.util.LinkedHashMap;
021import java.util.Map;
022
023import org.springframework.jdbc.core.SqlParameterValue;
024import org.springframework.util.Assert;
025
026/**
027 * {@link SqlParameterSource} implementation that holds a given Map of parameters.
028 *
029 * <p>This class is intended for passing in a simple Map of parameter values
030 * to the methods of the {@link NamedParameterJdbcTemplate} class.
031 *
032 * <p>The {@code addValue} methods on this class will make adding several values
033 * easier. The methods return a reference to the {@link MapSqlParameterSource}
034 * itself, so you can chain several method calls together within a single statement.
035 *
036 * @author Thomas Risberg
037 * @author Juergen Hoeller
038 * @since 2.0
039 * @see #addValue(String, Object)
040 * @see #addValue(String, Object, int)
041 * @see #registerSqlType
042 * @see NamedParameterJdbcTemplate
043 */
044public class MapSqlParameterSource extends AbstractSqlParameterSource {
045
046        private final Map<String, Object> values = new LinkedHashMap<String, Object>();
047
048
049        /**
050         * Create an empty MapSqlParameterSource,
051         * with values to be added via {@code addValue}.
052         * @see #addValue(String, Object)
053         */
054        public MapSqlParameterSource() {
055        }
056
057        /**
058         * Create a new MapSqlParameterSource, with one value
059         * comprised of the supplied arguments.
060         * @param paramName the name of the parameter
061         * @param value the value of the parameter
062         * @see #addValue(String, Object)
063         */
064        public MapSqlParameterSource(String paramName, Object value) {
065                addValue(paramName, value);
066        }
067
068        /**
069         * Create a new MapSqlParameterSource based on a Map.
070         * @param values a Map holding existing parameter values (can be {@code null})
071         */
072        public MapSqlParameterSource(Map<String, ?> values) {
073                addValues(values);
074        }
075
076
077        /**
078         * Add a parameter to this parameter source.
079         * @param paramName the name of the parameter
080         * @param value the value of the parameter
081         * @return a reference to this parameter source,
082         * so it's possible to chain several calls together
083         */
084        public MapSqlParameterSource addValue(String paramName, Object value) {
085                Assert.notNull(paramName, "Parameter name must not be null");
086                this.values.put(paramName, value);
087                if (value instanceof SqlParameterValue) {
088                        registerSqlType(paramName, ((SqlParameterValue) value).getSqlType());
089                }
090                return this;
091        }
092
093        /**
094         * Add a parameter to this parameter source.
095         * @param paramName the name of the parameter
096         * @param value the value of the parameter
097         * @param sqlType the SQL type of the parameter
098         * @return a reference to this parameter source,
099         * so it's possible to chain several calls together
100         */
101        public MapSqlParameterSource addValue(String paramName, Object value, int sqlType) {
102                Assert.notNull(paramName, "Parameter name must not be null");
103                this.values.put(paramName, value);
104                registerSqlType(paramName, sqlType);
105                return this;
106        }
107
108        /**
109         * Add a parameter to this parameter source.
110         * @param paramName the name of the parameter
111         * @param value the value of the parameter
112         * @param sqlType the SQL type of the parameter
113         * @param typeName the type name of the parameter
114         * @return a reference to this parameter source,
115         * so it's possible to chain several calls together
116         */
117        public MapSqlParameterSource addValue(String paramName, Object value, int sqlType, String typeName) {
118                Assert.notNull(paramName, "Parameter name must not be null");
119                this.values.put(paramName, value);
120                registerSqlType(paramName, sqlType);
121                registerTypeName(paramName, typeName);
122                return this;
123        }
124
125        /**
126         * Add a Map of parameters to this parameter source.
127         * @param values a Map holding existing parameter values (can be {@code null})
128         * @return a reference to this parameter source,
129         * so it's possible to chain several calls together
130         */
131        public MapSqlParameterSource addValues(Map<String, ?> values) {
132                if (values != null) {
133                        for (Map.Entry<String, ?> entry : values.entrySet()) {
134                                this.values.put(entry.getKey(), entry.getValue());
135                                if (entry.getValue() instanceof SqlParameterValue) {
136                                        SqlParameterValue value = (SqlParameterValue) entry.getValue();
137                                        registerSqlType(entry.getKey(), value.getSqlType());
138                                }
139                        }
140                }
141                return this;
142        }
143
144        /**
145         * Expose the current parameter values as read-only Map.
146         */
147        public Map<String, Object> getValues() {
148                return Collections.unmodifiableMap(this.values);
149        }
150
151
152        @Override
153        public boolean hasValue(String paramName) {
154                return this.values.containsKey(paramName);
155        }
156
157        @Override
158        public Object getValue(String paramName) {
159                if (!hasValue(paramName)) {
160                        throw new IllegalArgumentException("No value registered for key '" + paramName + "'");
161                }
162                return this.values.get(paramName);
163        }
164
165}