001/*
002 * Copyright 2002-2012 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.object;
018
019import org.springframework.jdbc.core.PreparedStatementCreator;
020import org.springframework.jdbc.core.PreparedStatementCreatorFactory;
021import org.springframework.jdbc.core.PreparedStatementSetter;
022import org.springframework.jdbc.core.namedparam.NamedParameterUtils;
023import org.springframework.jdbc.core.namedparam.ParsedSql;
024
025/**
026 * Operation object representing a SQL-based operation such as a query or update,
027 * as opposed to a stored procedure.
028 *
029 * <p>Configures a {@link org.springframework.jdbc.core.PreparedStatementCreatorFactory}
030 * based on the declared parameters.
031 *
032 * @author Rod Johnson
033 * @author Juergen Hoeller
034 */
035public abstract class SqlOperation extends RdbmsOperation {
036
037        /**
038         * Object enabling us to create PreparedStatementCreators efficiently,
039         * based on this class's declared parameters.
040         */
041        private PreparedStatementCreatorFactory preparedStatementFactory;
042
043        /** Parsed representation of the SQL statement */
044        private ParsedSql cachedSql;
045
046        /** Monitor for locking the cached representation of the parsed SQL statement */
047        private final Object parsedSqlMonitor = new Object();
048
049
050        /**
051         * Overridden method to configure the PreparedStatementCreatorFactory
052         * based on our declared parameters.
053         */
054        @Override
055        protected final void compileInternal() {
056                this.preparedStatementFactory = new PreparedStatementCreatorFactory(getSql(), getDeclaredParameters());
057                this.preparedStatementFactory.setResultSetType(getResultSetType());
058                this.preparedStatementFactory.setUpdatableResults(isUpdatableResults());
059                this.preparedStatementFactory.setReturnGeneratedKeys(isReturnGeneratedKeys());
060                if (getGeneratedKeysColumnNames() != null) {
061                        this.preparedStatementFactory.setGeneratedKeysColumnNames(getGeneratedKeysColumnNames());
062                }
063                this.preparedStatementFactory.setNativeJdbcExtractor(getJdbcTemplate().getNativeJdbcExtractor());
064
065                onCompileInternal();
066        }
067
068        /**
069         * Hook method that subclasses may override to post-process compilation.
070         * This implementation does nothing.
071         * @see #compileInternal
072         */
073        protected void onCompileInternal() {
074        }
075
076        /**
077         * Obtain a parsed representation of this operation's SQL statement.
078         * <p>Typically used for named parameter parsing.
079         */
080        protected ParsedSql getParsedSql() {
081                synchronized (this.parsedSqlMonitor) {
082                        if (this.cachedSql == null) {
083                                this.cachedSql = NamedParameterUtils.parseSqlStatement(getSql());
084                        }
085                        return this.cachedSql;
086                }
087        }
088
089
090        /**
091         * Return a PreparedStatementSetter to perform an operation
092         * with the given parameters.
093         * @param params the parameter array (may be {@code null})
094         */
095        protected final PreparedStatementSetter newPreparedStatementSetter(Object[] params) {
096                return this.preparedStatementFactory.newPreparedStatementSetter(params);
097        }
098
099        /**
100         * Return a PreparedStatementCreator to perform an operation
101         * with the given parameters.
102         * @param params the parameter array (may be {@code null})
103         */
104        protected final PreparedStatementCreator newPreparedStatementCreator(Object[] params) {
105                return this.preparedStatementFactory.newPreparedStatementCreator(params);
106        }
107
108        /**
109         * Return a PreparedStatementCreator to perform an operation
110         * with the given parameters.
111         * @param sqlToUse the actual SQL statement to use (if different from
112         * the factory's, for example because of named parameter expanding)
113         * @param params the parameter array (may be {@code null})
114         */
115        protected final PreparedStatementCreator newPreparedStatementCreator(String sqlToUse, Object[] params) {
116                return this.preparedStatementFactory.newPreparedStatementCreator(sqlToUse, params);
117        }
118
119}