All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate Maven / Gradle / Ivy

There is a newer version: 6.1.6
Show newest version
/*
 * Copyright 2002-2014 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.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.jdbc.core.namedparam;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.sql.DataSource;

import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.DataAccessUtils;
import org.springframework.jdbc.core.ColumnMapRowMapper;
import org.springframework.jdbc.core.JdbcOperations;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCallback;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.PreparedStatementCreatorFactory;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SingleColumnRowMapper;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.SqlRowSetResultSetExtractor;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.util.Assert;

/**
 * Template class with a basic set of JDBC operations, allowing the use
 * of named parameters rather than traditional '?' placeholders.
 *
 * 

This class delegates to a wrapped {@link #getJdbcOperations() JdbcTemplate} * once the substitution from named parameters to JDBC style '?' placeholders is * done at execution time. It also allows for expanding a {@link java.util.List} * of values to the appropriate number of placeholders. * *

The underlying {@link org.springframework.jdbc.core.JdbcTemplate} is * exposed to allow for convenient access to the traditional * {@link org.springframework.jdbc.core.JdbcTemplate} methods. * *

NOTE: An instance of this class is thread-safe once configured. * * @author Thomas Risberg * @author Juergen Hoeller * @since 2.0 * @see NamedParameterJdbcOperations * @see org.springframework.jdbc.core.JdbcTemplate */ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations { /** Default maximum number of entries for this template's SQL cache: 256 */ public static final int DEFAULT_CACHE_LIMIT = 256; /** The JdbcTemplate we are wrapping */ private final JdbcOperations classicJdbcTemplate; private volatile int cacheLimit = DEFAULT_CACHE_LIMIT; /** Cache of original SQL String to ParsedSql representation */ @SuppressWarnings("serial") private final Map parsedSqlCache = new LinkedHashMap(DEFAULT_CACHE_LIMIT, 0.75f, true) { @Override protected boolean removeEldestEntry(Map.Entry eldest) { return size() > getCacheLimit(); } }; /** * Create a new NamedParameterJdbcTemplate for the given {@link DataSource}. *

Creates a classic Spring {@link org.springframework.jdbc.core.JdbcTemplate} and wraps it. * @param dataSource the JDBC DataSource to access */ public NamedParameterJdbcTemplate(DataSource dataSource) { Assert.notNull(dataSource, "DataSource must not be null"); this.classicJdbcTemplate = new JdbcTemplate(dataSource); } /** * Create a new NamedParameterJdbcTemplate for the given classic * Spring {@link org.springframework.jdbc.core.JdbcTemplate}. * @param classicJdbcTemplate the classic Spring JdbcTemplate to wrap */ public NamedParameterJdbcTemplate(JdbcOperations classicJdbcTemplate) { Assert.notNull(classicJdbcTemplate, "JdbcTemplate must not be null"); this.classicJdbcTemplate = classicJdbcTemplate; } /** * Expose the classic Spring JdbcTemplate to allow invocation of * less commonly used methods. */ @Override public JdbcOperations getJdbcOperations() { return this.classicJdbcTemplate; } /** * Specify the maximum number of entries for this template's SQL cache. * Default is 256. */ public void setCacheLimit(int cacheLimit) { this.cacheLimit = cacheLimit; } /** * Return the maximum number of entries for this template's SQL cache. */ public int getCacheLimit() { return this.cacheLimit; } @Override public T execute(String sql, SqlParameterSource paramSource, PreparedStatementCallback action) throws DataAccessException { return getJdbcOperations().execute(getPreparedStatementCreator(sql, paramSource), action); } @Override public T execute(String sql, Map paramMap, PreparedStatementCallback action) throws DataAccessException { return execute(sql, new MapSqlParameterSource(paramMap), action); } @Override public T execute(String sql, PreparedStatementCallback action) throws DataAccessException { return execute(sql, EmptySqlParameterSource.INSTANCE, action); } @Override public T query(String sql, SqlParameterSource paramSource, ResultSetExtractor rse) throws DataAccessException { return getJdbcOperations().query(getPreparedStatementCreator(sql, paramSource), rse); } @Override public T query(String sql, Map paramMap, ResultSetExtractor rse) throws DataAccessException { return query(sql, new MapSqlParameterSource(paramMap), rse); } @Override public T query(String sql, ResultSetExtractor rse) throws DataAccessException { return query(sql, EmptySqlParameterSource.INSTANCE, rse); } @Override public void query(String sql, SqlParameterSource paramSource, RowCallbackHandler rch) throws DataAccessException { getJdbcOperations().query(getPreparedStatementCreator(sql, paramSource), rch); } @Override public void query(String sql, Map paramMap, RowCallbackHandler rch) throws DataAccessException { query(sql, new MapSqlParameterSource(paramMap), rch); } @Override public void query(String sql, RowCallbackHandler rch) throws DataAccessException { query(sql, EmptySqlParameterSource.INSTANCE, rch); } @Override public List query(String sql, SqlParameterSource paramSource, RowMapper rowMapper) throws DataAccessException { return getJdbcOperations().query(getPreparedStatementCreator(sql, paramSource), rowMapper); } @Override public List query(String sql, Map paramMap, RowMapper rowMapper) throws DataAccessException { return query(sql, new MapSqlParameterSource(paramMap), rowMapper); } @Override public List query(String sql, RowMapper rowMapper) throws DataAccessException { return query(sql, EmptySqlParameterSource.INSTANCE, rowMapper); } @Override public T queryForObject(String sql, SqlParameterSource paramSource, RowMapper rowMapper) throws DataAccessException { List results = getJdbcOperations().query(getPreparedStatementCreator(sql, paramSource), rowMapper); return DataAccessUtils.requiredSingleResult(results); } @Override public T queryForObject(String sql, Map paramMap, RowMapperrowMapper) throws DataAccessException { return queryForObject(sql, new MapSqlParameterSource(paramMap), rowMapper); } @Override public T queryForObject(String sql, SqlParameterSource paramSource, Class requiredType) throws DataAccessException { return queryForObject(sql, paramSource, new SingleColumnRowMapper(requiredType)); } @Override public T queryForObject(String sql, Map paramMap, Class requiredType) throws DataAccessException { return queryForObject(sql, paramMap, new SingleColumnRowMapper(requiredType)); } @Override public Map queryForMap(String sql, SqlParameterSource paramSource) throws DataAccessException { return queryForObject(sql, paramSource, new ColumnMapRowMapper()); } @Override public Map queryForMap(String sql, Map paramMap) throws DataAccessException { return queryForObject(sql, paramMap, new ColumnMapRowMapper()); } @Override public List queryForList(String sql, SqlParameterSource paramSource, Class elementType) throws DataAccessException { return query(sql, paramSource, new SingleColumnRowMapper(elementType)); } @Override public List queryForList(String sql, Map paramMap, Class elementType) throws DataAccessException { return queryForList(sql, new MapSqlParameterSource(paramMap), elementType); } @Override public List> queryForList(String sql, SqlParameterSource paramSource) throws DataAccessException { return query(sql, paramSource, new ColumnMapRowMapper()); } @Override public List> queryForList(String sql, Map paramMap) throws DataAccessException { return queryForList(sql, new MapSqlParameterSource(paramMap)); } @Override public SqlRowSet queryForRowSet(String sql, SqlParameterSource paramSource) throws DataAccessException { return getJdbcOperations().query( getPreparedStatementCreator(sql, paramSource), new SqlRowSetResultSetExtractor()); } @Override public SqlRowSet queryForRowSet(String sql, Map paramMap) throws DataAccessException { return queryForRowSet(sql, new MapSqlParameterSource(paramMap)); } @Override public int update(String sql, SqlParameterSource paramSource) throws DataAccessException { return getJdbcOperations().update(getPreparedStatementCreator(sql, paramSource)); } @Override public int update(String sql, Map paramMap) throws DataAccessException { return update(sql, new MapSqlParameterSource(paramMap)); } @Override public int update(String sql, SqlParameterSource paramSource, KeyHolder generatedKeyHolder) throws DataAccessException { return update(sql, paramSource, generatedKeyHolder, null); } @Override public int update( String sql, SqlParameterSource paramSource, KeyHolder generatedKeyHolder, String[] keyColumnNames) throws DataAccessException { ParsedSql parsedSql = getParsedSql(sql); String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource); Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null); List declaredParameters = NamedParameterUtils.buildSqlParameterList(parsedSql, paramSource); PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlToUse, declaredParameters); if (keyColumnNames != null) { pscf.setGeneratedKeysColumnNames(keyColumnNames); } else { pscf.setReturnGeneratedKeys(true); } return getJdbcOperations().update(pscf.newPreparedStatementCreator(params), generatedKeyHolder); } @Override public int[] batchUpdate(String sql, Map[] batchValues) { SqlParameterSource[] batchArgs = new SqlParameterSource[batchValues.length]; int i = 0; for (Map values : batchValues) { batchArgs[i] = new MapSqlParameterSource(values); i++; } return batchUpdate(sql, batchArgs); } @Override public int[] batchUpdate(String sql, SqlParameterSource[] batchArgs) { ParsedSql parsedSql = getParsedSql(sql); return NamedParameterBatchUpdateUtils.executeBatchUpdateWithNamedParameters(parsedSql, batchArgs, getJdbcOperations()); } /** * Build a PreparedStatementCreator based on the given SQL and named parameters. *

Note: Not used for the {@code update} variant with generated key handling. * @param sql SQL to execute * @param paramSource container of arguments to bind * @return the corresponding PreparedStatementCreator */ protected PreparedStatementCreator getPreparedStatementCreator(String sql, SqlParameterSource paramSource) { ParsedSql parsedSql = getParsedSql(sql); String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, paramSource); Object[] params = NamedParameterUtils.buildValueArray(parsedSql, paramSource, null); List declaredParameters = NamedParameterUtils.buildSqlParameterList(parsedSql, paramSource); PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlToUse, declaredParameters); return pscf.newPreparedStatementCreator(params); } /** * Obtain a parsed representation of the given SQL statement. *

The default implementation uses an LRU cache with an upper limit * of 256 entries. * @param sql the original SQL * @return a representation of the parsed SQL statement */ protected ParsedSql getParsedSql(String sql) { if (getCacheLimit() <= 0) { return NamedParameterUtils.parseSqlStatement(sql); } synchronized (this.parsedSqlCache) { ParsedSql parsedSql = this.parsedSqlCache.get(sql); if (parsedSql == null) { parsedSql = NamedParameterUtils.parseSqlStatement(sql); this.parsedSqlCache.put(sql, parsedSql); } return parsedSql; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy