/*
 * Copyright 2002-2018 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.object;

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

import org.springframework.jdbc.core.CallableStatementCreator;
import org.springframework.jdbc.core.CallableStatementCreatorFactory;
import org.springframework.jdbc.core.ParameterMapper;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

RdbmsOperation using a JdbcTemplate and representing a SQL-based call such as a stored procedure or a stored function.

Configures a CallableStatementCreatorFactory based on the declared parameters.

Author:Rod Johnson, Thomas Risberg
See Also:
/** * RdbmsOperation using a JdbcTemplate and representing a SQL-based * call such as a stored procedure or a stored function. * * <p>Configures a CallableStatementCreatorFactory based on the declared * parameters. * * @author Rod Johnson * @author Thomas Risberg * @see CallableStatementCreatorFactory */
public abstract class SqlCall extends RdbmsOperation {
Flag used to indicate that this call is for a function and to use the {? = call get_invoice_count(?)} syntax.
/** * Flag used to indicate that this call is for a function and to * use the {? = call get_invoice_count(?)} syntax. */
private boolean function = false;
Flag used to indicate that the sql for this call should be used exactly as it is defined. No need to add the escape syntax and parameter place holders.
/** * Flag used to indicate that the sql for this call should be used exactly as * it is defined. No need to add the escape syntax and parameter place holders. */
private boolean sqlReadyForUse = false;
Call string as defined in java.sql.CallableStatement. String of form {call add_invoice(?, ?, ?)} or {? = call get_invoice_count(?)} if isFunction is set to true. Updated after each parameter is added.
/** * Call string as defined in java.sql.CallableStatement. * String of form {call add_invoice(?, ?, ?)} or {? = call get_invoice_count(?)} * if isFunction is set to true. Updated after each parameter is added. */
@Nullable private String callString;
Object enabling us to create CallableStatementCreators efficiently, based on this class's declared parameters.
/** * Object enabling us to create CallableStatementCreators * efficiently, based on this class's declared parameters. */
@Nullable private CallableStatementCreatorFactory callableStatementFactory;
Constructor to allow use as a JavaBean. A DataSource, SQL and any parameters must be supplied before invoking the compile method and using this object.
See Also:
/** * Constructor to allow use as a JavaBean. * A DataSource, SQL and any parameters must be supplied before * invoking the {@code compile} method and using this object. * @see #setDataSource * @see #setSql * @see #compile */
public SqlCall() { }
Create a new SqlCall object with SQL, but without parameters. Must add parameters or settle with none.
Params:
  • ds – the DataSource to obtain connections from
  • sql – the SQL to execute
/** * Create a new SqlCall object with SQL, but without parameters. * Must add parameters or settle with none. * @param ds the DataSource to obtain connections from * @param sql the SQL to execute */
public SqlCall(DataSource ds, String sql) { setDataSource(ds); setSql(sql); }
Set whether this call is for a function.
/** * Set whether this call is for a function. */
public void setFunction(boolean function) { this.function = function; }
Return whether this call is for a function.
/** * Return whether this call is for a function. */
public boolean isFunction() { return this.function; }
Set whether the SQL can be used as is.
/** * Set whether the SQL can be used as is. */
public void setSqlReadyForUse(boolean sqlReadyForUse) { this.sqlReadyForUse = sqlReadyForUse; }
Return whether the SQL can be used as is.
/** * Return whether the SQL can be used as is. */
public boolean isSqlReadyForUse() { return this.sqlReadyForUse; }
Overridden method to configure the CallableStatementCreatorFactory based on our declared parameters.
See Also:
  • compileInternal.compileInternal()
/** * Overridden method to configure the CallableStatementCreatorFactory * based on our declared parameters. * @see RdbmsOperation#compileInternal() */
@Override protected final void compileInternal() { if (isSqlReadyForUse()) { this.callString = resolveSql(); } else { StringBuilder callString = new StringBuilder(32); List<SqlParameter> parameters = getDeclaredParameters(); int parameterCount = 0; if (isFunction()) { callString.append("{? = call ").append(resolveSql()).append('('); parameterCount = -1; } else { callString.append("{call ").append(resolveSql()).append('('); } for (SqlParameter parameter : parameters) { if (!parameter.isResultsParameter()) { if (parameterCount > 0) { callString.append(", "); } if (parameterCount >= 0) { callString.append('?'); } parameterCount++; } } callString.append(")}"); this.callString = callString.toString(); } if (logger.isDebugEnabled()) { logger.debug("Compiled stored procedure. Call string is [" + this.callString + "]"); } this.callableStatementFactory = new CallableStatementCreatorFactory(this.callString, getDeclaredParameters()); this.callableStatementFactory.setResultSetType(getResultSetType()); this.callableStatementFactory.setUpdatableResults(isUpdatableResults()); onCompileInternal(); }
Hook method that subclasses may override to react to compilation. This implementation does nothing.
/** * Hook method that subclasses may override to react to compilation. * This implementation does nothing. */
protected void onCompileInternal() { }
Get the call string.
/** * Get the call string. */
@Nullable public String getCallString() { return this.callString; }
Return a CallableStatementCreator to perform an operation with this parameters.
Params:
  • inParams – parameters. May be null.
/** * Return a CallableStatementCreator to perform an operation * with this parameters. * @param inParams parameters. May be {@code null}. */
protected CallableStatementCreator newCallableStatementCreator(@Nullable Map<String, ?> inParams) { Assert.state(this.callableStatementFactory != null, "No CallableStatementFactory available"); return this.callableStatementFactory.newCallableStatementCreator(inParams); }
Return a CallableStatementCreator to perform an operation with the parameters returned from this ParameterMapper.
Params:
  • inParamMapper – parametermapper. May not be null.
/** * Return a CallableStatementCreator to perform an operation * with the parameters returned from this ParameterMapper. * @param inParamMapper parametermapper. May not be {@code null}. */
protected CallableStatementCreator newCallableStatementCreator(ParameterMapper inParamMapper) { Assert.state(this.callableStatementFactory != null, "No CallableStatementFactory available"); return this.callableStatementFactory.newCallableStatementCreator(inParamMapper); } }