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