Browse Source

Polishing

(cherry picked from commit bbde68c49e)
pull/30971/head
Juergen Hoeller 3 years ago
parent
commit
23eb0e3128
  1. 7
      spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcOperations.java
  2. 10
      spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java
  3. 7
      spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/BeanPropertySqlParameterSource.java
  4. 11
      spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java
  5. 42
      spring-jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterQueryTests.java

7
spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcOperations.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -35,12 +35,13 @@ import org.springframework.lang.Nullable;
* <p>Alternatively, the standard JDBC infrastructure can be mocked. * <p>Alternatively, the standard JDBC infrastructure can be mocked.
* However, mocking this interface constitutes significantly less work. * However, mocking this interface constitutes significantly less work.
* As an alternative to a mock objects approach to testing data access code, * As an alternative to a mock objects approach to testing data access code,
* consider the powerful integration testing support provided via the <em>Spring * consider the powerful integration testing support provided via the
* TestContext Framework</em>, in the {@code spring-test} artifact. * <em>Spring TestContext Framework</em>, in the {@code spring-test} artifact.
* *
* @author Rod Johnson * @author Rod Johnson
* @author Juergen Hoeller * @author Juergen Hoeller
* @see JdbcTemplate * @see JdbcTemplate
* @see org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations
*/ */
public interface JdbcOperations { public interface JdbcOperations {

10
spring-jdbc/src/main/java/org/springframework/jdbc/core/JdbcTemplate.java

@ -65,8 +65,7 @@ import org.springframework.util.StringUtils;
* It executes core JDBC workflow, leaving application code to provide SQL * It executes core JDBC workflow, leaving application code to provide SQL
* and extract results. This class executes SQL queries or updates, initiating * and extract results. This class executes SQL queries or updates, initiating
* iteration over ResultSets and catching JDBC exceptions and translating * iteration over ResultSets and catching JDBC exceptions and translating
* them to the generic, more informative exception hierarchy defined in the * them to the common {@code org.springframework.dao} exception hierarchy.
* {@code org.springframework.dao} package.
* *
* <p>Code using this class need only implement callback interfaces, giving * <p>Code using this class need only implement callback interfaces, giving
* them a clearly defined contract. The {@link PreparedStatementCreator} callback * them a clearly defined contract. The {@link PreparedStatementCreator} callback
@ -75,7 +74,8 @@ import org.springframework.util.StringUtils;
* values from a ResultSet. See also {@link PreparedStatementSetter} and * values from a ResultSet. See also {@link PreparedStatementSetter} and
* {@link RowMapper} for two popular alternative callback interfaces. * {@link RowMapper} for two popular alternative callback interfaces.
* *
* <p>Can be used within a service implementation via direct instantiation * <p>An instance of this template class is thread-safe once configured.
* Can be used within a service implementation via direct instantiation
* with a DataSource reference, or get prepared in an application context * with a DataSource reference, or get prepared in an application context
* and given to services as bean reference. Note: The DataSource should * and given to services as bean reference. Note: The DataSource should
* always be configured as a bean in the application context, in the first case * always be configured as a bean in the application context, in the first case
@ -88,12 +88,11 @@ import org.springframework.util.StringUtils;
* <p>All SQL operations performed by this class are logged at debug level, * <p>All SQL operations performed by this class are logged at debug level,
* using "org.springframework.jdbc.core.JdbcTemplate" as log category. * using "org.springframework.jdbc.core.JdbcTemplate" as log category.
* *
* <p><b>NOTE: An instance of this class is thread-safe once configured.</b>
*
* @author Rod Johnson * @author Rod Johnson
* @author Juergen Hoeller * @author Juergen Hoeller
* @author Thomas Risberg * @author Thomas Risberg
* @since May 3, 2001 * @since May 3, 2001
* @see JdbcOperations
* @see PreparedStatementCreator * @see PreparedStatementCreator
* @see PreparedStatementSetter * @see PreparedStatementSetter
* @see CallableStatementCreator * @see CallableStatementCreator
@ -103,6 +102,7 @@ import org.springframework.util.StringUtils;
* @see RowCallbackHandler * @see RowCallbackHandler
* @see RowMapper * @see RowMapper
* @see org.springframework.jdbc.support.SQLExceptionTranslator * @see org.springframework.jdbc.support.SQLExceptionTranslator
* @see org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate
*/ */
public class JdbcTemplate extends JdbcAccessor implements JdbcOperations { public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {

7
spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/BeanPropertySqlParameterSource.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -32,9 +32,10 @@ import org.springframework.util.StringUtils;
/** /**
* {@link SqlParameterSource} implementation that obtains parameter values * {@link SqlParameterSource} implementation that obtains parameter values
* from bean properties of a given JavaBean object. The names of the bean * from bean properties of a given JavaBean object. The names of the bean
* properties have to match the parameter names. * properties have to match the parameter names. Supports components of
* record classes as well, with accessor methods matching parameter names.
* *
* <p>Uses a Spring BeanWrapper for bean property access underneath. * <p>Uses a Spring {@link BeanWrapper} for bean property access underneath.
* *
* @author Thomas Risberg * @author Thomas Risberg
* @author Juergen Hoeller * @author Juergen Hoeller

11
spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplate.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2020 the original author or authors. * Copyright 2002-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -55,16 +55,19 @@ import org.springframework.util.ConcurrentLruCache;
* done at execution time. It also allows for expanding a {@link java.util.List} * done at execution time. It also allows for expanding a {@link java.util.List}
* of values to the appropriate number of placeholders. * of values to the appropriate number of placeholders.
* *
* <p>The underlying {@link org.springframework.jdbc.core.JdbcTemplate} is * <p>An instance of this template class is thread-safe once configured.
* The underlying {@link org.springframework.jdbc.core.JdbcTemplate} is
* exposed to allow for convenient access to the traditional * exposed to allow for convenient access to the traditional
* {@link org.springframework.jdbc.core.JdbcTemplate} methods. * {@link org.springframework.jdbc.core.JdbcTemplate} methods.
* *
* <p><b>NOTE: An instance of this class is thread-safe once configured.</b>
*
* @author Thomas Risberg * @author Thomas Risberg
* @author Juergen Hoeller * @author Juergen Hoeller
* @since 2.0 * @since 2.0
* @see NamedParameterJdbcOperations * @see NamedParameterJdbcOperations
* @see SqlParameterSource
* @see ResultSetExtractor
* @see RowCallbackHandler
* @see RowMapper
* @see org.springframework.jdbc.core.JdbcTemplate * @see org.springframework.jdbc.core.JdbcTemplate
*/ */
public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations { public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations {

42
spring-jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterQueryTests.java

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2019 the original author or authors. * Copyright 2002-2023 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -34,8 +34,6 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.jdbc.core.RowMapper;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
@ -135,8 +133,7 @@ public class NamedParameterQueryTests {
} }
@Test @Test
public void testQueryForListWithParamMapAndIntegerElementAndSingleRowAndColumn() public void testQueryForListWithParamMapAndIntegerElementAndSingleRowAndColumn() throws Exception {
throws Exception {
given(resultSet.getMetaData()).willReturn(resultSetMetaData); given(resultSet.getMetaData()).willReturn(resultSetMetaData);
given(resultSet.next()).willReturn(true, false); given(resultSet.next()).willReturn(true, false);
given(resultSet.getInt(1)).willReturn(11); given(resultSet.getInt(1)).willReturn(11);
@ -174,11 +171,10 @@ public class NamedParameterQueryTests {
MapSqlParameterSource params = new MapSqlParameterSource(); MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("id", 3); params.addValue("id", 3);
Object o = template.queryForObject("SELECT AGE FROM CUSTMR WHERE ID = :id", Integer value = template.queryForObject("SELECT AGE FROM CUSTMR WHERE ID = :id",
params, (RowMapper<Object>) (rs, rowNum) -> rs.getInt(1)); params, (rs, rowNum) -> rs.getInt(1));
boolean condition = o instanceof Integer; assertThat(value).isEqualTo(22);
assertThat(condition).as("Correct result type").isTrue();
verify(connection).prepareStatement("SELECT AGE FROM CUSTMR WHERE ID = ?"); verify(connection).prepareStatement("SELECT AGE FROM CUSTMR WHERE ID = ?");
verify(preparedStatement).setObject(1, 3); verify(preparedStatement).setObject(1, 3);
} }
@ -191,11 +187,10 @@ public class NamedParameterQueryTests {
Map<String, Object> params = new HashMap<>(); Map<String, Object> params = new HashMap<>();
params.put("id", 3); params.put("id", 3);
Object o = template.queryForObject("SELECT AGE FROM CUSTMR WHERE ID = :id", Integer value = template.queryForObject("SELECT AGE FROM CUSTMR WHERE ID = :id",
params, Integer.class); params, Integer.class);
boolean condition = o instanceof Integer; assertThat(value).isEqualTo(22);
assertThat(condition).as("Correct result type").isTrue();
verify(connection).prepareStatement("SELECT AGE FROM CUSTMR WHERE ID = ?"); verify(connection).prepareStatement("SELECT AGE FROM CUSTMR WHERE ID = ?");
verify(preparedStatement).setObject(1, 3); verify(preparedStatement).setObject(1, 3);
} }
@ -208,30 +203,26 @@ public class NamedParameterQueryTests {
MapSqlParameterSource params = new MapSqlParameterSource(); MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("id", 3); params.addValue("id", 3);
Object o = template.queryForObject("SELECT AGE FROM CUSTMR WHERE ID = :id", Integer value = template.queryForObject("SELECT AGE FROM CUSTMR WHERE ID = :id",
params, Integer.class); params, Integer.class);
boolean condition = o instanceof Integer; assertThat(value).isEqualTo(22);
assertThat(condition).as("Correct result type").isTrue();
verify(connection).prepareStatement("SELECT AGE FROM CUSTMR WHERE ID = ?"); verify(connection).prepareStatement("SELECT AGE FROM CUSTMR WHERE ID = ?");
verify(preparedStatement).setObject(1, 3); verify(preparedStatement).setObject(1, 3);
} }
@Test @Test
public void testQueryForObjectWithParamMapAndList() throws Exception { public void testQueryForObjectWithParamMapAndList() throws Exception {
String sql = "SELECT AGE FROM CUSTMR WHERE ID IN (:ids)";
String sqlToUse = "SELECT AGE FROM CUSTMR WHERE ID IN (?, ?)";
given(resultSet.getMetaData()).willReturn(resultSetMetaData); given(resultSet.getMetaData()).willReturn(resultSetMetaData);
given(resultSet.next()).willReturn(true, false); given(resultSet.next()).willReturn(true, false);
given(resultSet.getInt(1)).willReturn(22); given(resultSet.getInt(1)).willReturn(22);
MapSqlParameterSource params = new MapSqlParameterSource(); MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("ids", Arrays.asList(3, 4)); params.addValue("ids", Arrays.asList(3, 4));
Object o = template.queryForObject(sql, params, Integer.class); Integer value = template.queryForObject("SELECT AGE FROM CUSTMR WHERE ID IN (:ids)", params, Integer.class);
boolean condition = o instanceof Integer; assertThat(value).isEqualTo(22);
assertThat(condition).as("Correct result type").isTrue(); verify(connection).prepareStatement("SELECT AGE FROM CUSTMR WHERE ID IN (?, ?)");
verify(connection).prepareStatement(sqlToUse);
verify(preparedStatement).setObject(1, 3); verify(preparedStatement).setObject(1, 3);
} }
@ -246,14 +237,11 @@ public class NamedParameterQueryTests {
l1.add(new Object[] {3, "Rod"}); l1.add(new Object[] {3, "Rod"});
l1.add(new Object[] {4, "Juergen"}); l1.add(new Object[] {4, "Juergen"});
params.addValue("multiExpressionList", l1); params.addValue("multiExpressionList", l1);
Object o = template.queryForObject( Integer value = template.queryForObject("SELECT AGE FROM CUSTMR WHERE (ID, NAME) IN (:multiExpressionList)",
"SELECT AGE FROM CUSTMR WHERE (ID, NAME) IN (:multiExpressionList)",
params, Integer.class); params, Integer.class);
boolean condition = o instanceof Integer; assertThat(value).isEqualTo(22);
assertThat(condition).as("Correct result type").isTrue(); verify(connection).prepareStatement("SELECT AGE FROM CUSTMR WHERE (ID, NAME) IN ((?, ?), (?, ?))");
verify(connection).prepareStatement(
"SELECT AGE FROM CUSTMR WHERE (ID, NAME) IN ((?, ?), (?, ?))");
verify(preparedStatement).setObject(1, 3); verify(preparedStatement).setObject(1, 3);
} }

Loading…
Cancel
Save