001/* 002 * Copyright 2002-2019 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.HashMap; 020import java.util.Map; 021import java.util.StringJoiner; 022 023import org.springframework.jdbc.core.SqlParameterValue; 024import org.springframework.jdbc.support.JdbcUtils; 025import org.springframework.lang.Nullable; 026import org.springframework.util.Assert; 027 028/** 029 * Abstract base class for {@link SqlParameterSource} implementations. 030 * Provides registration of SQL types per parameter and a friendly 031 * {@link #toString() toString} representation enumerating all parameters for 032 * a {@code SqlParameterSource} implementing {@link #getParameterNames()}. 033 * Concrete subclasses must implement {@link #hasValue} and {@link #getValue}. 034 * 035 * @author Juergen Hoeller 036 * @author Jens Schauder 037 * @since 2.0 038 * @see #hasValue(String) 039 * @see #getValue(String) 040 * @see #getParameterNames() 041 */ 042public abstract class AbstractSqlParameterSource implements SqlParameterSource { 043 044 private final Map<String, Integer> sqlTypes = new HashMap<>(); 045 046 private final Map<String, String> typeNames = new HashMap<>(); 047 048 049 /** 050 * Register an SQL type for the given parameter. 051 * @param paramName the name of the parameter 052 * @param sqlType the SQL type of the parameter 053 */ 054 public void registerSqlType(String paramName, int sqlType) { 055 Assert.notNull(paramName, "Parameter name must not be null"); 056 this.sqlTypes.put(paramName, sqlType); 057 } 058 059 /** 060 * Register an SQL type for the given parameter. 061 * @param paramName the name of the parameter 062 * @param typeName the type name of the parameter 063 */ 064 public void registerTypeName(String paramName, String typeName) { 065 Assert.notNull(paramName, "Parameter name must not be null"); 066 this.typeNames.put(paramName, typeName); 067 } 068 069 /** 070 * Return the SQL type for the given parameter, if registered. 071 * @param paramName the name of the parameter 072 * @return the SQL type of the parameter, 073 * or {@code TYPE_UNKNOWN} if not registered 074 */ 075 @Override 076 public int getSqlType(String paramName) { 077 Assert.notNull(paramName, "Parameter name must not be null"); 078 return this.sqlTypes.getOrDefault(paramName, TYPE_UNKNOWN); 079 } 080 081 /** 082 * Return the type name for the given parameter, if registered. 083 * @param paramName the name of the parameter 084 * @return the type name of the parameter, 085 * or {@code null} if not registered 086 */ 087 @Override 088 @Nullable 089 public String getTypeName(String paramName) { 090 Assert.notNull(paramName, "Parameter name must not be null"); 091 return this.typeNames.get(paramName); 092 } 093 094 095 /** 096 * Enumerate the parameter names and values with their corresponding SQL type if available, 097 * or just return the simple {@code SqlParameterSource} implementation class name otherwise. 098 * @since 5.2 099 * @see #getParameterNames() 100 */ 101 @Override 102 public String toString() { 103 String[] parameterNames = getParameterNames(); 104 if (parameterNames != null) { 105 StringJoiner result = new StringJoiner(", ", getClass().getSimpleName() + " {", "}"); 106 for (String parameterName : parameterNames) { 107 Object value = getValue(parameterName); 108 if (value instanceof SqlParameterValue) { 109 value = ((SqlParameterValue) value).getValue(); 110 } 111 String typeName = getTypeName(parameterName); 112 if (typeName == null) { 113 int sqlType = getSqlType(parameterName); 114 if (sqlType != TYPE_UNKNOWN) { 115 typeName = JdbcUtils.resolveTypeName(sqlType); 116 if (typeName == null) { 117 typeName = String.valueOf(sqlType); 118 } 119 } 120 } 121 StringBuilder entry = new StringBuilder(); 122 entry.append(parameterName).append('=').append(value); 123 if (typeName != null) { 124 entry.append(" (type:").append(typeName).append(')'); 125 } 126 result.add(entry); 127 } 128 return result.toString(); 129 } 130 else { 131 return getClass().getSimpleName(); 132 } 133 } 134 135}