AbstractSqlParameterSource enumerates parameter values in toString()
Closes gh-2080
This commit is contained in:
parent
4a5b9d39d4
commit
a11a592734
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2017 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -18,16 +18,26 @@ package org.springframework.jdbc.core.namedparam;
|
|||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import org.springframework.jdbc.core.SqlParameterValue;
|
||||
import org.springframework.jdbc.support.JdbcUtils;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link SqlParameterSource} implementations.
|
||||
* Provides registration of SQL types per parameter.
|
||||
* Provides registration of SQL types per parameter and a friendly
|
||||
* {@link #toString() toString} representation enumerating all parameters for
|
||||
* a {@code SqlParameterSource} implementing {@link #getParameterNames()}.
|
||||
* Concrete subclasses must implement {@link #hasValue} and {@link #getValue}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Jens Schauder
|
||||
* @since 2.0
|
||||
* @see #hasValue(String)
|
||||
* @see #getValue(String)
|
||||
* @see #getParameterNames()
|
||||
*/
|
||||
public abstract class AbstractSqlParameterSource implements SqlParameterSource {
|
||||
|
||||
|
|
@ -81,4 +91,45 @@ public abstract class AbstractSqlParameterSource implements SqlParameterSource {
|
|||
return this.typeNames.get(paramName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Enumerate the parameter names and values with their corresponding SQL type if available,
|
||||
* or just return the simple {@code SqlParameterSource} implementation class name otherwise.
|
||||
* @since 5.2
|
||||
* @see #getParameterNames()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
String[] parameterNames = getParameterNames();
|
||||
if (parameterNames != null) {
|
||||
StringJoiner result = new StringJoiner(", ", getClass().getSimpleName() + " {", "}");
|
||||
for (String parameterName : parameterNames) {
|
||||
Object value = getValue(parameterName);
|
||||
if (value instanceof SqlParameterValue) {
|
||||
value = ((SqlParameterValue) value).getValue();
|
||||
}
|
||||
String typeName = getTypeName(parameterName);
|
||||
if (typeName == null) {
|
||||
int sqlType = getSqlType(parameterName);
|
||||
if (sqlType != TYPE_UNKNOWN) {
|
||||
typeName = JdbcUtils.resolveTypeName(sqlType);
|
||||
if (typeName == null) {
|
||||
typeName = String.valueOf(sqlType);
|
||||
}
|
||||
}
|
||||
}
|
||||
StringBuilder entry = new StringBuilder();
|
||||
entry.append(parameterName).append('=').append(value);
|
||||
if (typeName != null) {
|
||||
entry.append(" (type:").append(typeName).append(')');
|
||||
}
|
||||
result.add(entry);
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
else {
|
||||
return getClass().getSimpleName();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -25,6 +25,7 @@ import org.springframework.beans.NotReadablePropertyException;
|
|||
import org.springframework.beans.PropertyAccessor;
|
||||
import org.springframework.beans.PropertyAccessorFactory;
|
||||
import org.springframework.jdbc.core.StatementCreatorUtils;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
|
|
@ -89,7 +90,7 @@ public class BeanPropertySqlParameterSource extends AbstractSqlParameterSource {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
@NonNull
|
||||
public String[] getParameterNames() {
|
||||
return getReadablePropertyNames();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -21,6 +21,7 @@ import java.util.LinkedHashMap;
|
|||
import java.util.Map;
|
||||
|
||||
import org.springframework.jdbc.core.SqlParameterValue;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
|
@ -165,7 +166,7 @@ public class MapSqlParameterSource extends AbstractSqlParameterSource {
|
|||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
@NonNull
|
||||
public String[] getParameterNames() {
|
||||
return StringUtils.toStringArray(this.values.keySet());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -89,7 +89,7 @@ public interface SqlParameterSource {
|
|||
}
|
||||
|
||||
/**
|
||||
* Extract all available parameter names if possible.
|
||||
* Enumerate all available parameter names if possible.
|
||||
* <p>This is an optional operation, primarily for use with
|
||||
* {@link org.springframework.jdbc.core.simple.SimpleJdbcInsert}
|
||||
* and {@link org.springframework.jdbc.core.simple.SimpleJdbcCall}.
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.jdbc.support;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.Blob;
|
||||
|
|
@ -28,6 +29,8 @@ import java.sql.SQLException;
|
|||
import java.sql.SQLFeatureNotSupportedException;
|
||||
import java.sql.Statement;
|
||||
import java.sql.Types;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
|
@ -56,6 +59,19 @@ public abstract class JdbcUtils {
|
|||
|
||||
private static final Log logger = LogFactory.getLog(JdbcUtils.class);
|
||||
|
||||
private static final Map<Integer, String> typeNames = new HashMap<>();
|
||||
|
||||
static {
|
||||
try {
|
||||
for (Field field : Types.class.getFields()) {
|
||||
typeNames.put((Integer) field.get(null), field.getName());
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Failed to resolve JDBC Types constants", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close the given JDBC Connection and ignore any thrown exception.
|
||||
|
|
@ -442,6 +458,18 @@ public abstract class JdbcUtils {
|
|||
Types.TINYINT == sqlType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the standard type name for the given SQL type, if possible.
|
||||
* @param sqlType the SQL type to resolve
|
||||
* @return the corresponding constant name in {@link java.sql.Types}
|
||||
* (e.g. "VARCHAR"/"NUMERIC"), or {@code null} if not resolvable
|
||||
* @since 5.2
|
||||
*/
|
||||
@Nullable
|
||||
public static String resolveTypeName(int sqlType) {
|
||||
return typeNames.get(sqlType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the column name to use. The column name is determined based on a
|
||||
* lookup using ResultSetMetaData.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -19,6 +19,7 @@ package org.springframework.jdbc.core.namedparam;
|
|||
import java.sql.Types;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
|
|
@ -29,16 +30,17 @@ import static org.junit.Assert.*;
|
|||
* @author Rick Evans
|
||||
* @author Juergen Hoeller
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class BeanPropertySqlParameterSourceTests {
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void withNullBeanPassedToCtor() throws Exception {
|
||||
public void withNullBeanPassedToCtor() {
|
||||
new BeanPropertySqlParameterSource(null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void getValueWhereTheUnderlyingBeanHasNoSuchProperty() throws Exception {
|
||||
public void getValueWhereTheUnderlyingBeanHasNoSuchProperty() {
|
||||
BeanPropertySqlParameterSource source = new BeanPropertySqlParameterSource(new TestBean());
|
||||
source.getValue("thisPropertyDoesNotExist");
|
||||
}
|
||||
|
|
@ -65,23 +67,57 @@ public class BeanPropertySqlParameterSourceTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void hasValueWhereTheUnderlyingBeanHasNoSuchProperty() throws Exception {
|
||||
public void hasValueWhereTheUnderlyingBeanHasNoSuchProperty() {
|
||||
BeanPropertySqlParameterSource source = new BeanPropertySqlParameterSource(new TestBean());
|
||||
assertFalse(source.hasValue("thisPropertyDoesNotExist"));
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void getValueWhereTheUnderlyingBeanPropertyIsNotReadable() throws Exception {
|
||||
public void getValueWhereTheUnderlyingBeanPropertyIsNotReadable() {
|
||||
BeanPropertySqlParameterSource source = new BeanPropertySqlParameterSource(new NoReadableProperties());
|
||||
source.getValue("noOp");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasValueWhereTheUnderlyingBeanPropertyIsNotReadable() throws Exception {
|
||||
public void hasValueWhereTheUnderlyingBeanPropertyIsNotReadable() {
|
||||
BeanPropertySqlParameterSource source = new BeanPropertySqlParameterSource(new NoReadableProperties());
|
||||
assertFalse(source.hasValue("noOp"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringShowsParameterDetails() {
|
||||
BeanPropertySqlParameterSource source = new BeanPropertySqlParameterSource(new TestBean("tb", 99));
|
||||
assertThat(source.toString(), Matchers.allOf(
|
||||
Matchers.startsWith("BeanPropertySqlParameterSource {"),
|
||||
Matchers.endsWith("}"),
|
||||
Matchers.containsString("name=tb (type:VARCHAR)"),
|
||||
Matchers.containsString("age=99 (type:INTEGER)")
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringShowsCustomSqlType() {
|
||||
BeanPropertySqlParameterSource source = new BeanPropertySqlParameterSource(new TestBean("tb", 99));
|
||||
source.registerSqlType("name", Integer.MAX_VALUE);
|
||||
assertThat(source.toString(), Matchers.allOf(
|
||||
Matchers.startsWith("BeanPropertySqlParameterSource {"),
|
||||
Matchers.endsWith("}"),
|
||||
Matchers.containsString("name=tb (type:" + Integer.MAX_VALUE + ")"),
|
||||
Matchers.containsString("age=99 (type:INTEGER)")
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringDoesNotShowTypeUnknown() {
|
||||
BeanPropertySqlParameterSource source = new BeanPropertySqlParameterSource(new TestBean("tb", 99));
|
||||
assertThat(source.toString(), Matchers.allOf(
|
||||
Matchers.startsWith("BeanPropertySqlParameterSource {"),
|
||||
Matchers.endsWith("}"),
|
||||
Matchers.containsString("beanFactory=null"),
|
||||
Matchers.not(Matchers.containsString("beanFactory=null (type:"))
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final class NoReadableProperties {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2006 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -16,36 +16,58 @@
|
|||
|
||||
package org.springframework.jdbc.core.namedparam;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.jdbc.core.SqlParameterValue;
|
||||
import org.springframework.jdbc.support.JdbcUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rick Evans
|
||||
* @author Arjen Poutsma
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class MapSqlParameterSourceTests {
|
||||
|
||||
@Test
|
||||
public void nullParameterValuesPassedToCtorIsOk() throws Exception {
|
||||
public void nullParameterValuesPassedToCtorIsOk() {
|
||||
new MapSqlParameterSource(null);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void getValueChokesIfParameterIsNotPresent() throws Exception {
|
||||
public void getValueChokesIfParameterIsNotPresent() {
|
||||
MapSqlParameterSource source = new MapSqlParameterSource();
|
||||
source.getValue("pechorin was right!");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sqlParameterValueRegistersSqlType() throws Exception {
|
||||
MapSqlParameterSource msps = new MapSqlParameterSource("FOO", new SqlParameterValue(2, "Foo"));
|
||||
public void sqlParameterValueRegistersSqlType() {
|
||||
MapSqlParameterSource msps = new MapSqlParameterSource("FOO", new SqlParameterValue(Types.NUMERIC, "Foo"));
|
||||
assertEquals("Correct SQL Type not registered", 2, msps.getSqlType("FOO"));
|
||||
MapSqlParameterSource msps2 = new MapSqlParameterSource();
|
||||
msps2.addValues(msps.getValues());
|
||||
assertEquals("Correct SQL Type not registered", 2, msps2.getSqlType("FOO"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringShowsParameterDetails() {
|
||||
MapSqlParameterSource source = new MapSqlParameterSource("FOO", new SqlParameterValue(Types.NUMERIC, "Foo"));
|
||||
assertEquals("MapSqlParameterSource {FOO=Foo (type:NUMERIC)}", source.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringShowsCustomSqlType() {
|
||||
MapSqlParameterSource source = new MapSqlParameterSource("FOO", new SqlParameterValue(Integer.MAX_VALUE, "Foo"));
|
||||
assertEquals("MapSqlParameterSource {FOO=Foo (type:" + Integer.MAX_VALUE + ")}", source.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void toStringDoesNotShowTypeUnknown() {
|
||||
MapSqlParameterSource source = new MapSqlParameterSource("FOO", new SqlParameterValue(JdbcUtils.TYPE_UNKNOWN, "Foo"));
|
||||
assertEquals("MapSqlParameterSource {FOO=Foo}", source.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package org.springframework.jdbc.support;
|
||||
|
||||
import java.sql.Types;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
|
@ -24,6 +26,7 @@ import static org.junit.Assert.*;
|
|||
* Unit tests for {@link JdbcUtils}.
|
||||
*
|
||||
* @author Thomas Risberg
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class JdbcUtilsTests {
|
||||
|
||||
|
|
@ -36,6 +39,14 @@ public class JdbcUtilsTests {
|
|||
assertEquals("MySQL", JdbcUtils.commonDatabaseName("MySQL"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void resolveTypeName() {
|
||||
assertEquals("VARCHAR", JdbcUtils.resolveTypeName(Types.VARCHAR));
|
||||
assertEquals("NUMERIC", JdbcUtils.resolveTypeName(Types.NUMERIC));
|
||||
assertEquals("INTEGER", JdbcUtils.resolveTypeName(Types.INTEGER));
|
||||
assertNull(JdbcUtils.resolveTypeName(JdbcUtils.TYPE_UNKNOWN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void convertUnderscoreNameToPropertyName() {
|
||||
assertEquals("myName", JdbcUtils.convertUnderscoreNameToPropertyName("MY_NAME"));
|
||||
|
|
|
|||
Loading…
Reference in New Issue