提交 c236f9fa 编写于 作者: A Arjen Poutsma

Initial import of JDBC module

上级 8c87d847
<?xml version="1.0" encoding="UTF-8"?>
<project name="org.springframework.jdbc">
<property file="${basedir}/../build.properties"/>
<import file="${basedir}/../build-spring-framework/package-bundle.xml"/>
<import file="${basedir}/../spring-build/standard/default.xml"/>
</project>
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="http://ivyrep.jayasoft.org/ivy-doc.xsl"?>
<ivy-module
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://incubator.apache.org/ivy/schemas/ivy.xsd"
version="1.3">
<info organisation="org.springframework" module="${ant.project.name}">
<license name="Apache 2.0" url="http://www.apache.org/licenses/LICENSE-2.0"/>
</info>
<configurations>
<include file="${spring.build.dir}/common/default-ivy-configurations.xml"/>
</configurations>
<publications>
<artifact name="${ant.project.name}"/>
<artifact name="${ant.project.name}-sources" type="src" ext="jar"/>
</publications>
<dependencies>
<!-- compile dependencies -->
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.logging" rev="1.1.1" conf="compile->runtime" />
<dependency org="org.springframework" name="org.springframework.core" rev="latest.integration" conf="compile->compile" />
<dependency org="org.springframework" name="org.springframework.beans" rev="latest.integration" conf="compile->compile" />
<dependency org="org.springframework" name="org.springframework.aop" rev="latest.integration" conf="compile->compile" />
<dependency org="org.springframework" name="org.springframework.transaction" rev="latest.integration" conf="compile->compile" />
<!-- optional dependencies -->
<dependency org="org.springframework" name="org.springframework.context" rev="latest.integration" conf="optional->compile" />
<dependency org="javax.transaction" name="com.springsource.javax.transaction" rev="1.1.0" conf="optional->compile" />
<dependency org="com.mchange.c3p0" name="com.springsource.com.mchange.v2.c3p0" rev="0.9.1.2" conf="optional->compile" />
<dependency org="com.experlog.xapool" name="com.springsource.org.enhydra.jdbc" rev="1.5.0" conf="optional->compile" />
<!-- test dependencies -->
<dependency org="org.junit" name="com.springsource.org.junit" rev="4.4.0" conf="test->runtime" />
</dependencies>
</ivy-module>
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>org.springframework.core</artifactId>
<packaging>jar</packaging>
<name>Spring Core Abstractions and Utilities</name>
<version>3.0.0.M1</version>
<repositories>
<repository>
<id>com.springsource.repository.bundles.external</id>
<name>SpringSource Enterprise Bundle Repository - External Bundle Releases</name>
<url>http://repository.springsource.com/maven/bundles/external</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>com.springsource.org.apache.commons.logging</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.log4j</groupId>
<artifactId>com.springsource.org.apache.log4j</artifactId>
<version>1.2.15</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>com.springsource.org.apache.commons.collections</artifactId>
<version>3.2.0</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>com.springsource.org.aspectj.weaver</artifactId>
<version>1.6.2.RELEASE</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.objectweb.asm</groupId>
<artifactId>com.springsource.org.objectweb.asm.commons</artifactId>
<version>2.2.3</version>
<optional>true</optional>
</dependency>
</dependencies>
</project>
\ No newline at end of file
/*
* Copyright 2002-2008 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;
import java.sql.SQLException;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
/**
* Exception thrown when SQL specified is invalid. Such exceptions always have
* a <code>java.sql.SQLException</code> root cause.
*
* <p>It would be possible to have subclasses for no such table, no such column etc.
* A custom SQLExceptionTranslator could create such more specific exceptions,
* without affecting code using this class.
*
* @author Rod Johnson
* @see InvalidResultSetAccessException
*/
public class BadSqlGrammarException extends InvalidDataAccessResourceUsageException {
private String sql;
/**
* Constructor for BadSqlGrammarException.
* @param task name of current task
* @param sql the offending SQL statement
* @param ex the root cause
*/
public BadSqlGrammarException(String task, String sql, SQLException ex) {
super(task + "; bad SQL grammar [" + sql + "]", ex);
this.sql = sql;
}
/**
* Return the wrapped SQLException.
*/
public SQLException getSQLException() {
return (SQLException) getCause();
}
/**
* Return the SQL that caused the problem.
*/
public String getSql() {
return this.sql;
}
}
/*
* Copyright 2002-2008 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;
import java.sql.SQLException;
import org.springframework.dao.DataAccessResourceFailureException;
/**
* Fatal exception thrown when we can't connect to an RDBMS using JDBC.
*
* @author Rod Johnson
*/
public class CannotGetJdbcConnectionException extends DataAccessResourceFailureException {
/**
* Constructor for CannotGetJdbcConnectionException.
* @param msg the detail message
* @param ex SQLException root cause
*/
public CannotGetJdbcConnectionException(String msg, SQLException ex) {
super(msg, ex);
}
/**
* Constructor for CannotGetJdbcConnectionException.
* @param msg the detail message
* @param ex ClassNotFoundException root cause
* @deprecated since Spring 2.5, in favor of throwing an
* IllegalStateException in case of the driver not being found
*/
public CannotGetJdbcConnectionException(String msg, ClassNotFoundException ex) {
super(msg, ex);
}
}
/*
* Copyright 2002-2008 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;
import org.springframework.dao.DataRetrievalFailureException;
/**
* Data access exception thrown when a result set did not have the correct column count,
* for example when expecting a single column but getting 0 or more than 1 columns.
*
* @author Juergen Hoeller
* @since 2.0
* @see org.springframework.dao.IncorrectResultSizeDataAccessException
*/
public class IncorrectResultSetColumnCountException extends DataRetrievalFailureException {
private int expectedCount;
private int actualCount;
/**
* Constructor for IncorrectResultSetColumnCountException.
* @param expectedCount the expected column count
* @param actualCount the actual column count
*/
public IncorrectResultSetColumnCountException(int expectedCount, int actualCount) {
super("Incorrect column count: expected " + expectedCount + ", actual " + actualCount);
this.expectedCount = expectedCount;
this.actualCount = actualCount;
}
/**
* Constructor for IncorrectResultCountDataAccessException.
* @param msg the detail message
* @param expectedCount the expected column count
* @param actualCount the actual column count
*/
public IncorrectResultSetColumnCountException(String msg, int expectedCount, int actualCount) {
super(msg);
this.expectedCount = expectedCount;
this.actualCount = actualCount;
}
/**
* Return the expected column count.
*/
public int getExpectedCount() {
return this.expectedCount;
}
/**
* Return the actual column count.
*/
public int getActualCount() {
return this.actualCount;
}
}
/*
* Copyright 2002-2008 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;
import java.sql.SQLException;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
/**
* Exception thrown when a ResultSet has been accessed in an invalid fashion.
* Such exceptions always have a <code>java.sql.SQLException</code> root cause.
*
* <p>This typically happens when an invalid ResultSet column index or name
* has been specified. Also thrown by disconnected SqlRowSets.
*
* @author Juergen Hoeller
* @since 1.2
* @see BadSqlGrammarException
* @see org.springframework.jdbc.support.rowset.SqlRowSet
*/
public class InvalidResultSetAccessException extends InvalidDataAccessResourceUsageException {
private String sql;
/**
* Constructor for InvalidResultSetAccessException.
* @param task name of current task
* @param sql the offending SQL statement
* @param ex the root cause
*/
public InvalidResultSetAccessException(String task, String sql, SQLException ex) {
super(task + "; invalid ResultSet access for SQL [" + sql + "]", ex);
this.sql = sql;
}
/**
* Constructor for InvalidResultSetAccessException.
* @param ex the root cause
*/
public InvalidResultSetAccessException(SQLException ex) {
super(ex.getMessage(), ex);
}
/**
* Return the wrapped SQLException.
*/
public SQLException getSQLException() {
return (SQLException) getCause();
}
/**
* Return the SQL that caused the problem.
* @return the offending SQL, if known
*/
public String getSql() {
return this.sql;
}
}
/*
* Copyright 2002-2006 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;
import org.springframework.dao.IncorrectUpdateSemanticsDataAccessException;
/**
* Exception thrown when a JDBC update affects an unexpected number of rows.
* Typically we expect an update to affect a single row, meaning it's an
* error if it affects multiple rows.
*
* @author Rod Johnson
* @author Juergen Hoeller
*/
public class JdbcUpdateAffectedIncorrectNumberOfRowsException extends IncorrectUpdateSemanticsDataAccessException {
/** Number of rows that should have been affected */
private int expected;
/** Number of rows that actually were affected */
private int actual;
/**
* Constructor for JdbcUpdateAffectedIncorrectNumberOfRowsException.
* @param sql SQL we were tring to execute
* @param expected the expected number of rows affected
* @param actual the actual number of rows affected
*/
public JdbcUpdateAffectedIncorrectNumberOfRowsException(String sql, int expected, int actual) {
super("SQL update '" + sql + "' affected " + actual + " rows, not " + expected + " as expected");
this.expected = expected;
this.actual = actual;
}
/**
* Return the number of rows that should have been affected.
*/
public int getExpectedRowsAffected() {
return this.expected;
}
/**
* Return the number of rows that have actually been affected.
*/
public int getActualRowsAffected() {
return this.actual;
}
public boolean wasDataUpdated() {
return (getActualRowsAffected() > 0);
}
}
/*
* Copyright 2002-2005 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;
import java.io.IOException;
import org.springframework.dao.DataRetrievalFailureException;
/**
* Exception to be thrown when a LOB could not be retrieved.
*
* @author Juergen Hoeller
* @since 1.0.2
*/
public class LobRetrievalFailureException extends DataRetrievalFailureException {
/**
* Constructor for LobRetrievalFailureException.
* @param msg the detail message
*/
public LobRetrievalFailureException(String msg) {
super(msg);
}
/**
* Constructor for LobRetrievalFailureException.
* @param msg the detail message
* @param ex IOException root cause
*/
public LobRetrievalFailureException(String msg, IOException ex) {
super(msg, ex);
}
}
/*
* Copyright 2002-2006 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;
import java.sql.SQLWarning;
import org.springframework.dao.UncategorizedDataAccessException;
/**
* Exception thrown when we're not ignoring {@link java.sql.SQLWarning SQLWarnings}.
*
* <p>If a SQLWarning is reported, the operation completed, so we will need
* to explicitly roll it back if we're not happy when looking at the warning.
* We might choose to ignore (and log) the warning, or to wrap and throw it
* in the shape of this SQLWarningException instead.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see org.springframework.jdbc.core.JdbcTemplate#setIgnoreWarnings
*/
public class SQLWarningException extends UncategorizedDataAccessException {
/**
* Constructor for SQLWarningException.
* @param msg the detail message
* @param ex the JDBC warning
*/
public SQLWarningException(String msg, SQLWarning ex) {
super(msg, ex);
}
/**
* Return the underlying SQLWarning.
*/
public SQLWarning SQLWarning() {
return (SQLWarning) getCause();
}
}
/*
* Copyright 2002-2007 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;
import java.sql.SQLException;
import org.springframework.dao.UncategorizedDataAccessException;
/**
* Exception thrown when we can't classify a SQLException into
* one of our generic data access exceptions.
*
* @author Rod Johnson
* @author Juergen Hoeller
*/
public class UncategorizedSQLException extends UncategorizedDataAccessException {
/** SQL that led to the problem */
private final String sql;
/**
* Constructor for UncategorizedSQLException.
* @param task name of current task
* @param sql the offending SQL statement
* @param ex the root cause
*/
public UncategorizedSQLException(String task, String sql, SQLException ex) {
super(task + "; uncategorized SQLException for SQL [" + sql + "]; SQL state [" +
ex.getSQLState() + "]; error code [" + ex.getErrorCode() + "]; " + ex.getMessage(), ex);
this.sql = sql;
}
/**
* Return the underlying SQLException.
*/
public SQLException getSQLException() {
return (SQLException) getCause();
}
/**
* Return the SQL that led to the problem.
*/
public String getSql() {
return this.sql;
}
}
/*
* Copyright 2002-2007 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;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* Simple adapter for PreparedStatementSetter that applies
* a given array of arguments.
*
* @author Juergen Hoeller
*/
class ArgPreparedStatementSetter implements PreparedStatementSetter, ParameterDisposer {
private final Object[] args;
/**
* Create a new ArgPreparedStatementSetter for the given arguments.
* @param args the arguments to set
*/
public ArgPreparedStatementSetter(Object[] args) {
this.args = args;
}
public void setValues(PreparedStatement ps) throws SQLException {
if (this.args != null) {
for (int i = 0; i < this.args.length; i++) {
Object arg = this.args[i];
if (arg instanceof SqlParameterValue) {
SqlParameterValue paramValue = (SqlParameterValue) arg;
StatementCreatorUtils.setParameterValue(ps, i + 1, paramValue, paramValue.getValue());
}
else {
StatementCreatorUtils.setParameterValue(ps, i + 1, SqlTypeValue.TYPE_UNKNOWN, arg);
}
}
}
}
public void cleanupParameters() {
StatementCreatorUtils.cleanupParameters(this.args);
}
}
/*
* Copyright 2002-2007 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;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Collection;
import java.util.Iterator;
import org.springframework.dao.InvalidDataAccessApiUsageException;
/**
* Simple adapter for PreparedStatementSetter that applies
* given arrays of arguments and JDBC argument types.
*
* @author Juergen Hoeller
*/
class ArgTypePreparedStatementSetter implements PreparedStatementSetter, ParameterDisposer {
private final Object[] args;
private final int[] argTypes;
/**
* Create a new ArgTypePreparedStatementSetter for the given arguments.
* @param args the arguments to set
* @param argTypes the corresponding SQL types of the arguments
*/
public ArgTypePreparedStatementSetter(Object[] args, int[] argTypes) {
if ((args != null && argTypes == null) || (args == null && argTypes != null) ||
(args != null && args.length != argTypes.length)) {
throw new InvalidDataAccessApiUsageException("args and argTypes parameters must match");
}
this.args = args;
this.argTypes = argTypes;
}
public void setValues(PreparedStatement ps) throws SQLException {
int argIndx = 1;
if (this.args != null) {
for (int i = 0; i < this.args.length; i++) {
Object arg = this.args[i];
if (arg instanceof Collection && this.argTypes[i] != Types.ARRAY) {
Collection entries = (Collection) arg;
for (Iterator it = entries.iterator(); it.hasNext();) {
Object entry = it.next();
if (entry instanceof Object[]) {
Object[] valueArray = ((Object[])entry);
for (int k = 0; k < valueArray.length; k++) {
Object argValue = valueArray[k];
StatementCreatorUtils.setParameterValue(ps, argIndx++, this.argTypes[i], argValue);
}
}
else {
StatementCreatorUtils.setParameterValue(ps, argIndx++, this.argTypes[i], entry);
}
}
}
else {
StatementCreatorUtils.setParameterValue(ps, argIndx++, this.argTypes[i], arg);
}
}
}
}
public void cleanupParameters() {
StatementCreatorUtils.cleanupParameters(this.args);
}
}
/*
* Copyright 2002-2007 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;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* Batch update callback interface used by the {@link JdbcTemplate} class.
*
* <p>This interface sets values on a {@link java.sql.PreparedStatement} provided
* by the JdbcTemplate class, for each of a number of updates in a batch using the
* same SQL. Implementations are responsible for setting any necessary parameters.
* SQL with placeholders will already have been supplied.
*
* <p>Implementations <i>do not</i> need to concern themselves with SQLExceptions
* that may be thrown from operations they attempt. The JdbcTemplate class will
* catch and handle SQLExceptions appropriately.
*
* @author Rod Johnson
* @since March 2, 2003
* @see JdbcTemplate#batchUpdate(String, BatchPreparedStatementSetter)
* @see InterruptibleBatchPreparedStatementSetter
*/
public interface BatchPreparedStatementSetter {
/**
* Set parameter values on the given PreparedStatement.
* @param ps the PreparedStatement to invoke setter methods on
* @param i index of the statement we're issuing in the batch, starting from 0
* @throws SQLException if a SQLException is encountered
* (i.e. there is no need to catch SQLException)
*/
void setValues(PreparedStatement ps, int i) throws SQLException;
/**
* Return the size of the batch.
* @return the number of statements in the batch
*/
int getBatchSize();
}
/*
* Copyright 2002-2008 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;
import java.beans.PropertyDescriptor;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.NotWritablePropertyException;
import org.springframework.beans.PropertyAccessorFactory;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.util.Assert;
/**
* {@link RowMapper} implementation that converts a row into a new instance
* of the specified mapped target class. The mapped target class must be a
* top-level class and it must have a default or no-arg constructor.
*
* <p>Column values are mapped based on matching the column name as obtained from result set
* metadata to public setters for the corresponding properties. The names are matched either
* directly or by transforming a name separating the parts with underscores to the same name
* using "camel" case.
*
* <p>Mapping is provided for fields in the target class for many common types, e.g.:
* String, boolean, Boolean, byte, Byte, short, Short, int, Integer, long, Long,
* float, Float, double, Double, BigDecimal, <code>java.util.Date</code>, etc.
*
* <p>To facilitate mapping between columns and fields that don't have matching names,
* try using column aliases in the SQL statement like "select fname as first_name from customer".
*
* <p>Please note that this class is designed to provide convenience rather than high performance.
* For best performance consider using a custom RowMapper.
*
* @author Thomas Risberg
* @author Juergen Hoeller
* @since 2.5
*/
public class BeanPropertyRowMapper implements RowMapper {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
/** The class we are mapping to */
private Class mappedClass;
/** Whether we're strictly validating */
private boolean checkFullyPopulated = false;
/** Map of the fields we provide mapping for */
private Map mappedFields;
/** Set of bean properties we provide mapping for */
private Set mappedProperties;
/**
* Create a new BeanPropertyRowMapper for bean-style configuration.
* @see #setMappedClass
* @see #setCheckFullyPopulated
*/
public BeanPropertyRowMapper() {
}
/**
* Create a new BeanPropertyRowMapper, accepting unpopulated properties
* in the target bean.
* @param mappedClass the class that each row should be mapped to
*/
public BeanPropertyRowMapper(Class mappedClass) {
initialize(mappedClass);
}
/**
* Create a new BeanPropertyRowMapper.
* @param mappedClass the class that each row should be mapped to
* @param checkFullyPopulated whether we're strictly validating that
* all bean properties have been mapped from corresponding database fields
*/
public BeanPropertyRowMapper(Class mappedClass, boolean checkFullyPopulated) {
initialize(mappedClass);
this.checkFullyPopulated = checkFullyPopulated;
}
/**
* Set the class that each row should be mapped to.
*/
public void setMappedClass(Class mappedClass) {
if (this.mappedClass == null) {
initialize(mappedClass);
}
else {
if (!this.mappedClass.equals(mappedClass)) {
throw new InvalidDataAccessApiUsageException("The mapped class can not be reassigned to map to " +
mappedClass + " since it is already providing mapping for " + this.mappedClass);
}
}
}
/**
* Initialize the mapping metadata for the given class.
* @param mappedClass the mapped class.
*/
protected void initialize(Class mappedClass) {
this.mappedClass = mappedClass;
this.mappedFields = new HashMap();
this.mappedProperties = new HashSet();
PropertyDescriptor[] pds = BeanUtils.getPropertyDescriptors(mappedClass);
for (int i = 0; i < pds.length; i++) {
PropertyDescriptor pd = pds[i];
if (pd.getWriteMethod() != null) {
this.mappedFields.put(pd.getName().toLowerCase(), pd);
String underscoredName = underscoreName(pd.getName());
if (!pd.getName().toLowerCase().equals(underscoredName)) {
this.mappedFields.put(underscoredName, pd);
}
this.mappedProperties.add(pd.getName());
}
}
}
/**
* Convert a name in camelCase to an underscored name in lower case.
* Any upper case letters are converted to lower case with a preceding underscore.
* @param name the string containing original name
* @return the converted name
*/
private String underscoreName(String name) {
StringBuffer result = new StringBuffer();
if (name != null && name.length() > 0) {
result.append(name.substring(0, 1).toLowerCase());
for (int i = 1; i < name.length(); i++) {
String s = name.substring(i, i + 1);
if (s.equals(s.toUpperCase())) {
result.append("_");
result.append(s.toLowerCase());
}
else {
result.append(s);
}
}
}
return result.toString();
}
/**
* Get the class that we are mapping to.
*/
public final Class getMappedClass() {
return this.mappedClass;
}
/**
* Set whether we're strictly validating that all bean properties have been
* mapped from corresponding database fields.
* <p>Default is <code>false</code>, accepting unpopulated properties in the
* target bean.
*/
public void setCheckFullyPopulated(boolean checkFullyPopulated) {
this.checkFullyPopulated = checkFullyPopulated;
}
/**
* Return whether we're strictly validating that all bean properties have been
* mapped from corresponding database fields.
*/
public boolean isCheckFullyPopulated() {
return this.checkFullyPopulated;
}
/**
* Extract the values for all columns in the current row.
* <p>Utilizes public setters and result set metadata.
* @see java.sql.ResultSetMetaData
*/
public Object mapRow(ResultSet rs, int rowNumber) throws SQLException {
Assert.state(this.mappedClass != null, "Mapped class was not specified");
Object mappedObject = BeanUtils.instantiateClass(this.mappedClass);
BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(mappedObject);
initBeanWrapper(bw);
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
Set populatedProperties = (isCheckFullyPopulated() ? new HashSet() : null);
for (int index = 1; index <= columnCount; index++) {
String column = JdbcUtils.lookupColumnName(rsmd, index).toLowerCase();
PropertyDescriptor pd = (PropertyDescriptor) this.mappedFields.get(column);
if (pd != null) {
try {
Object value = getColumnValue(rs, index, pd);
if (logger.isDebugEnabled() && rowNumber == 0) {
logger.debug("Mapping column '" + column + "' to property '" +
pd.getName() + "' of type " + pd.getPropertyType());
}
bw.setPropertyValue(pd.getName(), value);
if (populatedProperties != null) {
populatedProperties.add(pd.getName());
}
}
catch (NotWritablePropertyException ex) {
throw new DataRetrievalFailureException(
"Unable to map column " + column + " to property " + pd.getName(), ex);
}
}
}
if (populatedProperties != null && !populatedProperties.equals(this.mappedProperties)) {
throw new InvalidDataAccessApiUsageException("Given ResultSet does not contain all fields " +
"necessary to populate object of class [" + this.mappedClass + "]: " + this.mappedProperties);
}
return mappedObject;
}
/**
* Initialize the given BeanWrapper to be used for row mapping.
* To be called for each row.
* <p>The default implementation is empty. Can be overridden in subclasses.
* @param bw the BeanWrapper to initialize
*/
protected void initBeanWrapper(BeanWrapper bw) {
}
/**
* Retrieve a JDBC object value for the specified column.
* <p>The default implementation calls
* {@link JdbcUtils#getResultSetValue(java.sql.ResultSet, int, Class)}.
* Subclasses may override this to check specific value types upfront,
* or to post-process values return from <code>getResultSetValue</code>.
* @param rs is the ResultSet holding the data
* @param index is the column index
* @param pd the bean property that each result object is expected to match
* (or <code>null</code> if none specified)
* @return the Object value
* @throws SQLException in case of extraction failure
* @see org.springframework.jdbc.support.JdbcUtils#getResultSetValue(java.sql.ResultSet, int, Class)
*/
protected Object getColumnValue(ResultSet rs, int index, PropertyDescriptor pd) throws SQLException {
return JdbcUtils.getResultSetValue(rs, index, pd.getPropertyType());
}
}
/*
* Copyright 2002-2005 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;
import java.sql.CallableStatement;
import java.sql.SQLException;
import org.springframework.dao.DataAccessException;
/**
* Generic callback interface for code that operates on a CallableStatement.
* Allows to execute any number of operations on a single CallableStatement,
* for example a single execute call or repeated execute calls with varying
* parameters.
*
* <p>Used internally by JdbcTemplate, but also useful for application code.
* Note that the passed-in CallableStatement can have been created by the
* framework or by a custom CallableStatementCreator. However, the latter is
* hardly ever necessary, as most custom callback actions will perform updates
* in which case a standard CallableStatement is fine. Custom actions will
* always set parameter values themselves, so that CallableStatementCreator
* capability is not needed either.
*
* @author Juergen Hoeller
* @since 16.03.2004
* @see JdbcTemplate#execute(String, CallableStatementCallback)
* @see JdbcTemplate#execute(CallableStatementCreator, CallableStatementCallback)
*/
public interface CallableStatementCallback {
/**
* Gets called by <code>JdbcTemplate.execute</code> with an active JDBC
* CallableStatement. Does not need to care about closing the Statement
* or the Connection, or about handling transactions: this will all be
* handled by Spring's JdbcTemplate.
*
* <p><b>NOTE:</b> Any ResultSets opened should be closed in finally blocks
* within the callback implementation. Spring will close the Statement
* object after the callback returned, but this does not necessarily imply
* that the ResultSet resources will be closed: the Statement objects might
* get pooled by the connection pool, with <code>close</code> calls only
* returning the object to the pool but not physically closing the resources.
*
* <p>If called without a thread-bound JDBC transaction (initiated by
* DataSourceTransactionManager), the code will simply get executed on the
* JDBC connection with its transactional semantics. If JdbcTemplate is
* configured to use a JTA-aware DataSource, the JDBC connection and thus
* the callback code will be transactional if a JTA transaction is active.
*
* <p>Allows for returning a result object created within the callback, i.e.
* a domain object or a collection of domain objects. A thrown RuntimeException
* is treated as application exception: it gets propagated to the caller of
* the template.
*
* @param cs active JDBC CallableStatement
* @return a result object, or <code>null</code> if none
* @throws SQLException if thrown by a JDBC method, to be auto-converted
* into a DataAccessException by a SQLExceptionTranslator
* @throws DataAccessException in case of custom exceptions
*/
Object doInCallableStatement(CallableStatement cs) throws SQLException, DataAccessException;
}
/*
* Copyright 2002-2005 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;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;
/**
* One of the three central callback interfaces used by the JdbcTemplate class.
* This interface creates a CallableStatement given a connection, provided
* by the JdbcTemplate class. Implementations are responsible for providing
* SQL and any necessary parameters.
*
* <p>Implementations <i>do not</i> need to concern themselves with
* SQLExceptions that may be thrown from operations they attempt.
* The JdbcTemplate class will catch and handle SQLExceptions appropriately.
*
* <p>A PreparedStatementCreator should also implement the SqlProvider interface
* if it is able to provide the SQL it uses for PreparedStatement creation.
* This allows for better contextual information in case of exceptions.
*
* @author Rod Johnson
* @author Thomas Risberg
* @see JdbcTemplate#execute(CallableStatementCreator, CallableStatementCallback)
* @see JdbcTemplate#call
* @see SqlProvider
*/
public interface CallableStatementCreator {
/**
* Create a callable statement in this connection. Allows implementations to use
* CallableStatements.
* @param con Connection to use to create statement
* @return a callable statement
* @throws SQLException there is no need to catch SQLExceptions
* that may be thrown in the implementation of this method.
* The JdbcTemplate class will handle them.
*/
CallableStatement createCallableStatement(Connection con) throws SQLException;
}
/*
* Copyright 2002-2008 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;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
/**
* Helper class that efficiently creates multiple {@link CallableStatementCreator}
* objects with different parameters based on a SQL statement and a single
* set of parameter declarations.
*
* @author Rod Johnson
* @author Thomas Risberg
* @author Juergen Hoeller
*/
public class CallableStatementCreatorFactory {
/** The SQL call string, which won't change when the parameters change. */
private final String callString;
/** List of SqlParameter objects. May not be <code>null</code>. */
private final List declaredParameters;
private int resultSetType = ResultSet.TYPE_FORWARD_ONLY;
private boolean updatableResults = false;
private NativeJdbcExtractor nativeJdbcExtractor;
/**
* Create a new factory. Will need to add parameters via the
* {@link #addParameter} method or have no parameters.
*/
public CallableStatementCreatorFactory(String callString) {
this.callString = callString;
this.declaredParameters = new LinkedList();
}
/**
* Create a new factory with the given SQL and the given parameters.
* @param callString the SQL call string
* @param declaredParameters list of {@link SqlParameter} objects
*/
public CallableStatementCreatorFactory(String callString, List declaredParameters) {
this.callString = callString;
this.declaredParameters = declaredParameters;
}
/**
* Add a new declared parameter.
* <p>Order of parameter addition is significant.
* @param param the parameter to add to the list of declared parameters
*/
public void addParameter(SqlParameter param) {
this.declaredParameters.add(param);
}
/**
* Set whether to use prepared statements that return a specific type of ResultSet.
* specific type of ResultSet.
* @param resultSetType the ResultSet type
* @see java.sql.ResultSet#TYPE_FORWARD_ONLY
* @see java.sql.ResultSet#TYPE_SCROLL_INSENSITIVE
* @see java.sql.ResultSet#TYPE_SCROLL_SENSITIVE
*/
public void setResultSetType(int resultSetType) {
this.resultSetType = resultSetType;
}
/**
* Set whether to use prepared statements capable of returning updatable ResultSets.
*/
public void setUpdatableResults(boolean updatableResults) {
this.updatableResults = updatableResults;
}
/**
* Specify the NativeJdbcExtractor to use for unwrapping CallableStatements, if any.
*/
public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) {
this.nativeJdbcExtractor = nativeJdbcExtractor;
}
/**
* Return a new CallableStatementCreator instance given this parameters.
* @param params list of parameters (may be <code>null</code>)
*/
public CallableStatementCreator newCallableStatementCreator(Map params) {
return new CallableStatementCreatorImpl(params != null ? params : new HashMap());
}
/**
* Return a new CallableStatementCreator instance given this parameter mapper.
* @param inParamMapper ParameterMapper implementation that will return a Map of parameters
*/
public CallableStatementCreator newCallableStatementCreator(ParameterMapper inParamMapper) {
return new CallableStatementCreatorImpl(inParamMapper);
}
/**
* CallableStatementCreator implementation returned by this class.
*/
private class CallableStatementCreatorImpl implements CallableStatementCreator, SqlProvider, ParameterDisposer {
private ParameterMapper inParameterMapper;
private Map inParameters;
/**
* Create a new CallableStatementCreatorImpl.
* @param inParamMapper ParameterMapper implementation for mapping input parameters
*/
public CallableStatementCreatorImpl(ParameterMapper inParamMapper) {
this.inParameterMapper = inParamMapper;
}
/**
* Create a new CallableStatementCreatorImpl.
* @param inParams list of SqlParameter objects
*/
public CallableStatementCreatorImpl(Map inParams) {
this.inParameters = inParams;
}
public CallableStatement createCallableStatement(Connection con) throws SQLException {
// If we were given a ParameterMapper, we must let the mapper do its thing to create the Map.
if (this.inParameterMapper != null) {
this.inParameters = this.inParameterMapper.createMap(con);
}
else {
if (this.inParameters == null) {
throw new InvalidDataAccessApiUsageException(
"A ParameterMapper or a Map of parameters must be provided");
}
}
CallableStatement cs = null;
if (resultSetType == ResultSet.TYPE_FORWARD_ONLY && !updatableResults) {
cs = con.prepareCall(callString);
}
else {
cs = con.prepareCall(callString, resultSetType,
updatableResults ? ResultSet.CONCUR_UPDATABLE : ResultSet.CONCUR_READ_ONLY);
}
// Determine CallabeStatement to pass to custom types.
CallableStatement csToUse = cs;
if (nativeJdbcExtractor != null) {
csToUse = nativeJdbcExtractor.getNativeCallableStatement(cs);
}
int sqlColIndx = 1;
for (int i = 0; i < declaredParameters.size(); i++) {
SqlParameter declaredParam = (SqlParameter) declaredParameters.get(i);
if (!declaredParam.isResultsParameter()) {
// So, it's a call parameter - part of the call string.
// Get the value - it may still be null.
Object inValue = this.inParameters.get(declaredParam.getName());
if (declaredParam instanceof ResultSetSupportingSqlParameter) {
// It's an output parameter: SqlReturnResultSet parameters already excluded.
// It need not (but may be) supplied by the caller.
if (declaredParam instanceof SqlOutParameter) {
if (declaredParam.getTypeName() != null) {
cs.registerOutParameter(sqlColIndx, declaredParam.getSqlType(), declaredParam.getTypeName());
}
else {
if (declaredParam.getScale() != null) {
cs.registerOutParameter(sqlColIndx, declaredParam.getSqlType(), declaredParam.getScale().intValue());
}
else {
cs.registerOutParameter(sqlColIndx, declaredParam.getSqlType());
}
}
if (declaredParam.isInputValueProvided()) {
StatementCreatorUtils.setParameterValue(csToUse, sqlColIndx, declaredParam, inValue);
}
}
}
else {
// It's an input parameter; must be supplied by the caller.
if (!this.inParameters.containsKey(declaredParam.getName())) {
throw new InvalidDataAccessApiUsageException(
"Required input parameter '" + declaredParam.getName() + "' is missing");
}
StatementCreatorUtils.setParameterValue(csToUse, sqlColIndx, declaredParam, inValue);
}
sqlColIndx++;
}
}
return cs;
}
public String getSql() {
return callString;
}
public void cleanupParameters() {
if (this.inParameters != null) {
StatementCreatorUtils.cleanupParameters(this.inParameters.values());
}
}
public String toString() {
StringBuffer buf = new StringBuffer("CallableStatementCreatorFactory.CallableStatementCreatorImpl: sql=[");
buf.append(callString).append("]; parameters=").append(this.inParameters);
return buf.toString();
}
}
}
/*
* Copyright 2002-2007 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;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Map;
import org.springframework.core.CollectionFactory;
import org.springframework.jdbc.support.JdbcUtils;
/**
* {@link RowMapper} implementation that creates a <code>java.util.Map</code>
* for each row, representing all columns as key-value pairs: one
* entry for each column, with the column name as key.
*
* <p>The Map implementation to use and the key to use for each column
* in the column Map can be customized through overriding
* {@link #createColumnMap} and {@link #getColumnKey}, respectively.
*
* <p><b>Note:</b> By default, ColumnMapRowMapper will try to build a linked Map
* with case-insensitive keys, to preserve column order as well as allow any
* casing to be used for column names. This requires Commons Collections on the
* classpath (which will be autodetected). Else, the fallback is a standard linked
* HashMap, which will still preserve column order but requires the application
* to specify the column names in the same casing as exposed by the driver.
*
* @author Juergen Hoeller
* @since 1.2
* @see JdbcTemplate#queryForList(String)
* @see JdbcTemplate#queryForMap(String)
*/
public class ColumnMapRowMapper implements RowMapper {
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
ResultSetMetaData rsmd = rs.getMetaData();
int columnCount = rsmd.getColumnCount();
Map mapOfColValues = createColumnMap(columnCount);
for (int i = 1; i <= columnCount; i++) {
String key = getColumnKey(JdbcUtils.lookupColumnName(rsmd, i));
Object obj = getColumnValue(rs, i);
mapOfColValues.put(key, obj);
}
return mapOfColValues;
}
/**
* Create a Map instance to be used as column map.
* <p>By default, a linked case-insensitive Map will be created if possible,
* else a plain HashMap (see Spring's CollectionFactory).
* @param columnCount the column count, to be used as initial
* capacity for the Map
* @return the new Map instance
* @see org.springframework.core.CollectionFactory#createLinkedCaseInsensitiveMapIfPossible
*/
protected Map createColumnMap(int columnCount) {
return CollectionFactory.createLinkedCaseInsensitiveMapIfPossible(columnCount);
}
/**
* Determine the key to use for the given column in the column Map.
* @param columnName the column name as returned by the ResultSet
* @return the column key to use
* @see java.sql.ResultSetMetaData#getColumnName
*/
protected String getColumnKey(String columnName) {
return columnName;
}
/**
* Retrieve a JDBC object value for the specified column.
* <p>The default implementation uses the <code>getObject</code> method.
* Additionally, this implementation includes a "hack" to get around Oracle
* returning a non standard object for their TIMESTAMP datatype.
* @param rs is the ResultSet holding the data
* @param index is the column index
* @return the Object returned
* @see org.springframework.jdbc.support.JdbcUtils#getResultSetValue
*/
protected Object getColumnValue(ResultSet rs, int index) throws SQLException {
return JdbcUtils.getResultSetValue(rs, index);
}
}
/*
* Copyright 2002-2005 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;
import java.sql.Connection;
import java.sql.SQLException;
import org.springframework.dao.DataAccessException;
/**
* Generic callback interface for code that operates on a JDBC Connection.
* Allows to execute any number of operations on a single Connection,
* using any type and number of Statements.
*
* <p>This is particularly useful for delegating to existing data access code
* that expects a Connection to work on and throws SQLException. For newly
* written code, it is strongly recommended to use JdbcTemplate's more specific
* operations, for example a <code>query</code> or <code>update</code> variant.
*
* @author Juergen Hoeller
* @since 1.1.3
* @see JdbcTemplate#execute(ConnectionCallback)
* @see JdbcTemplate#query
* @see JdbcTemplate#update
*/
public interface ConnectionCallback {
/**
* Gets called by <code>JdbcTemplate.execute</code> with an active JDBC
* Connection. Does not need to care about activating or closing the
* Connection, or handling transactions.
*
* <p>If called without a thread-bound JDBC transaction (initiated by
* DataSourceTransactionManager), the code will simply get executed on the
* JDBC connection with its transactional semantics. If JdbcTemplate is
* configured to use a JTA-aware DataSource, the JDBC Connection and thus
* the callback code will be transactional if a JTA transaction is active.
*
* <p>Allows for returning a result object created within the callback, i.e.
* a domain object or a collection of domain objects. Note that there's special
* support for single step actions: see <code>JdbcTemplate.queryForObject</code>
* etc. A thrown RuntimeException is treated as application exception:
* it gets propagated to the caller of the template.
*
* @param con active JDBC Connection
* @return a result object, or <code>null</code> if none
* @throws SQLException if thrown by a JDBC method, to be auto-converted
* to a DataAccessException by a SQLExceptionTranslator
* @throws DataAccessException in case of custom exceptions
* @see JdbcTemplate#queryForObject(String, Class)
* @see JdbcTemplate#queryForRowSet(String)
*/
Object doInConnection(Connection con) throws SQLException, DataAccessException;
}
/*
* Copyright 2002-2008 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;
/**
* Subinterface of {@link SqlTypeValue} that adds a cleanup callback,
* to be invoked after the value has been set and the corresponding
* statement has been executed.
*
* @author Juergen Hoeller
* @since 1.1
* @see org.springframework.jdbc.core.support.SqlLobValue
*/
public interface DisposableSqlTypeValue extends SqlTypeValue {
/**
* Clean up resources held by this type value,
* for example the LobCreator in case of a SqlLobValue.
* @see org.springframework.jdbc.core.support.SqlLobValue#cleanup()
* @see org.springframework.jdbc.support.SqlValue#cleanup()
*/
void cleanup();
}
/*
* Copyright 2002-2007 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;
/**
* Extension of the {@link BatchPreparedStatementSetter} interface,
* adding a batch exhaustion check.
*
* <p>This interface allows you to signal the end of a batch rather than
* having to determine the exact batch size upfront. Batch size is still
* being honored but it is now the maximum size of the batch.
*
* <p>The {@link #isBatchExhausted} method is called after each call to
* {@link #setValues} to determine whether there were some values added,
* or if the batch was determined to be complete and no additional values
* were provided during the last call to <code>setValues</code>.
*
* <p>Consider extending the
* {@link org.springframework.jdbc.core.support.AbstractInterruptibleBatchPreparedStatementSetter}
* base class instead of implementing this interface directly, using a single
* <code>setValuesIfAvailable</code> callback method that checks for available
* values and sets them, returning whether values have actually been provided.
*
* @author Thomas Risberg
* @author Juergen Hoeller
* @since 2.0
* @see JdbcTemplate#batchUpdate(String, BatchPreparedStatementSetter)
* @see org.springframework.jdbc.core.support.AbstractInterruptibleBatchPreparedStatementSetter
*/
public interface InterruptibleBatchPreparedStatementSetter extends BatchPreparedStatementSetter {
/**
* Return whether the batch is complete, that is, whether there were no
* additional values added during the last <code>setValues</code> call.
* <p><b>NOTE:</b> If this method returns <code>true</code>, any parameters
* that might have been set during the last <code>setValues</code> call will
* be ignored! Make sure that you set a corresponding internal flag if you
* detect exhaustion <i>at the beginning</i> of your <code>setValues</code>
* implementation, letting this method return <code>true</code> based on the flag.
* @param i index of the statement we're issuing in the batch, starting from 0
* @return whether the batch is already exhausted
* @see #setValues
* @see org.springframework.jdbc.core.support.AbstractInterruptibleBatchPreparedStatementSetter#setValuesIfAvailable
*/
boolean isBatchExhausted(int i);
}
/*
* Copyright 2002-2005 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;
/**
* Interface to be implemented by objects that can close resources
* allocated by parameters like SqlLobValues.
*
* <p>Typically implemented by PreparedStatementCreators and
* PreparedStatementSetters that support DisposableSqlTypeValue
* objects (e.g. SqlLobValue) as parameters.
*
* @author Thomas Risberg
* @author Juergen Hoeller
* @since 1.1
* @see PreparedStatementCreator
* @see PreparedStatementSetter
* @see DisposableSqlTypeValue
* @see org.springframework.jdbc.core.support.SqlLobValue
*/
public interface ParameterDisposer {
/**
* Close the resources allocated by parameters that the implementing
* object holds, for example in case of a DisposableSqlTypeValue
* (like a SqlLobValue).
* @see DisposableSqlTypeValue#cleanup
* @see org.springframework.jdbc.core.support.SqlLobValue#cleanup
*/
public void cleanupParameters();
}
/*
* Copyright 2002-2006 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;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
/**
* Implement this interface when parameters need to be customized based
* on the connection. We might need to do this to make use of proprietary
* features, available only with a specific Connection type.
*
* @author Rod Johnson
* @author Thomas Risberg
* @see CallableStatementCreatorFactory#newCallableStatementCreator(ParameterMapper)
* @see org.springframework.jdbc.object.StoredProcedure#execute(ParameterMapper)
*/
public interface ParameterMapper {
/**
* Create a Map of input parameters, keyed by name.
* @param con JDBC connection. This is useful (and the purpose of this interface)
* if we need to do something RDBMS-specific with a proprietary Connection
* implementation class. This class conceals such proprietary details. However,
* it is best to avoid using such proprietary RDBMS features if possible.
* @throws SQLException if a SQLException is encountered setting
* parameter values (that is, there's no need to catch SQLException)
* @return Map of input parameters, keyed by name (never <code>null</code>)
*/
Map createMap(Connection con) throws SQLException;
}
/*
* Copyright 2002-2005 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;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import org.springframework.dao.DataAccessException;
/**
* Generic callback interface for code that operates on a PreparedStatement.
* Allows to execute any number of operations on a single PreparedStatement,
* for example a single <code>executeUpdate</code> call or repeated
* <code>executeUpdate</code> calls with varying parameters.
*
* <p>Used internally by JdbcTemplate, but also useful for application code.
* Note that the passed-in PreparedStatement can have been created by the
* framework or by a custom PreparedStatementCreator. However, the latter is
* hardly ever necessary, as most custom callback actions will perform updates
* in which case a standard PreparedStatement is fine. Custom actions will
* always set parameter values themselves, so that PreparedStatementCreator
* capability is not needed either.
*
* @author Juergen Hoeller
* @since 16.03.2004
* @see JdbcTemplate#execute(String, PreparedStatementCallback)
* @see JdbcTemplate#execute(PreparedStatementCreator, PreparedStatementCallback)
*/
public interface PreparedStatementCallback {
/**
* Gets called by <code>JdbcTemplate.execute</code> with an active JDBC
* PreparedStatement. Does not need to care about closing the Statement
* or the Connection, or about handling transactions: this will all be
* handled by Spring's JdbcTemplate.
*
* <p><b>NOTE:</b> Any ResultSets opened should be closed in finally blocks
* within the callback implementation. Spring will close the Statement
* object after the callback returned, but this does not necessarily imply
* that the ResultSet resources will be closed: the Statement objects might
* get pooled by the connection pool, with <code>close</code> calls only
* returning the object to the pool but not physically closing the resources.
*
* <p>If called without a thread-bound JDBC transaction (initiated by
* DataSourceTransactionManager), the code will simply get executed on the
* JDBC connection with its transactional semantics. If JdbcTemplate is
* configured to use a JTA-aware DataSource, the JDBC connection and thus
* the callback code will be transactional if a JTA transaction is active.
*
* <p>Allows for returning a result object created within the callback, i.e.
* a domain object or a collection of domain objects. Note that there's
* special support for single step actions: see JdbcTemplate.queryForObject etc.
* A thrown RuntimeException is treated as application exception, it gets
* propagated to the caller of the template.
*
* @param ps active JDBC PreparedStatement
* @return a result object, or <code>null</code> if none
* @throws SQLException if thrown by a JDBC method, to be auto-converted
* to a DataAccessException by a SQLExceptionTranslator
* @throws DataAccessException in case of custom exceptions
* @see JdbcTemplate#queryForObject(String, Object[], Class)
* @see JdbcTemplate#queryForList(String, Object[])
*/
Object doInPreparedStatement(PreparedStatement ps) throws SQLException, DataAccessException;
}
/*
* Copyright 2002-2005 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;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* One of the two central callback interfaces used by the JdbcTemplate class.
* This interface creates a PreparedStatement given a connection, provided
* by the JdbcTemplate class. Implementations are responsible for providing
* SQL and any necessary parameters.
*
* <p>Implementations <i>do not</i> need to concern themselves with
* SQLExceptions that may be thrown from operations they attempt.
* The JdbcTemplate class will catch and handle SQLExceptions appropriately.
*
* <p>A PreparedStatementCreator should also implement the SqlProvider interface
* if it is able to provide the SQL it uses for PreparedStatement creation.
* This allows for better contextual information in case of exceptions.
*
* @author Rod Johnson
* @see JdbcTemplate#execute(PreparedStatementCreator, PreparedStatementCallback)
* @see JdbcTemplate#query(PreparedStatementCreator, RowCallbackHandler)
* @see JdbcTemplate#update(PreparedStatementCreator)
* @see SqlProvider
*/
public interface PreparedStatementCreator {
/**
* Create a statement in this connection. Allows implementations to use
* PreparedStatements. The JdbcTemplate will close the created statement.
* @param con Connection to use to create statement
* @return a prepared statement
* @throws SQLException there is no need to catch SQLExceptions
* that may be thrown in the implementation of this method.
* The JdbcTemplate class will handle them.
*/
PreparedStatement createPreparedStatement(Connection con) throws SQLException;
}
/*
* Copyright 2002-2008 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;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
import org.springframework.util.Assert;
/**
* Helper class that efficiently creates multiple {@link PreparedStatementCreator}
* objects with different parameters based on a SQL statement and a single
* set of parameter declarations.
*
* @author Rod Johnson
* @author Thomas Risberg
* @author Juergen Hoeller
*/
public class PreparedStatementCreatorFactory {
/** The SQL, which won't change when the parameters change */
private final String sql;
/** List of SqlParameter objects. May not be <code>null</code>. */
private final List declaredParameters;
private int resultSetType = ResultSet.TYPE_FORWARD_ONLY;
private boolean updatableResults = false;
private boolean returnGeneratedKeys = false;
private String[] generatedKeysColumnNames = null;
private NativeJdbcExtractor nativeJdbcExtractor;
/**
* Create a new factory. Will need to add parameters via the
* {@link #addParameter} method or have no parameters.
*/
public PreparedStatementCreatorFactory(String sql) {
this.sql = sql;
this.declaredParameters = new LinkedList();
}
/**
* Create a new factory with the given SQL and JDBC types.
* @param sql SQL to execute
* @param types int array of JDBC types
*/
public PreparedStatementCreatorFactory(String sql, int[] types) {
this.sql = sql;
this.declaredParameters = SqlParameter.sqlTypesToAnonymousParameterList(types);
}
/**
* Create a new factory with the given SQL and parameters.
* @param sql SQL
* @param declaredParameters list of {@link SqlParameter} objects
* @see SqlParameter
*/
public PreparedStatementCreatorFactory(String sql, List declaredParameters) {
this.sql = sql;
this.declaredParameters = declaredParameters;
}
/**
* Add a new declared parameter.
* <p>Order of parameter addition is significant.
* @param param the parameter to add to the list of declared parameters
*/
public void addParameter(SqlParameter param) {
this.declaredParameters.add(param);
}
/**
* Set whether to use prepared statements that return a specific type of ResultSet.
* @param resultSetType the ResultSet type
* @see java.sql.ResultSet#TYPE_FORWARD_ONLY
* @see java.sql.ResultSet#TYPE_SCROLL_INSENSITIVE
* @see java.sql.ResultSet#TYPE_SCROLL_SENSITIVE
*/
public void setResultSetType(int resultSetType) {
this.resultSetType = resultSetType;
}
/**
* Set whether to use prepared statements capable of returning updatable ResultSets.
*/
public void setUpdatableResults(boolean updatableResults) {
this.updatableResults = updatableResults;
}
/**
* Set whether prepared statements should be capable of returning auto-generated keys.
*/
public void setReturnGeneratedKeys(boolean returnGeneratedKeys) {
this.returnGeneratedKeys = returnGeneratedKeys;
}
/**
* Set the column names of the auto-generated keys.
*/
public void setGeneratedKeysColumnNames(String[] names) {
this.generatedKeysColumnNames = names;
}
/**
* Specify the NativeJdbcExtractor to use for unwrapping PreparedStatements, if any.
*/
public void setNativeJdbcExtractor(NativeJdbcExtractor nativeJdbcExtractor) {
this.nativeJdbcExtractor = nativeJdbcExtractor;
}
/**
* Return a new PreparedStatementSetter for the given parameters.
* @param params list of parameters (may be <code>null</code>)
*/
public PreparedStatementSetter newPreparedStatementSetter(List params) {
return new PreparedStatementCreatorImpl(params != null ? params : Collections.EMPTY_LIST);
}
/**
* Return a new PreparedStatementSetter for the given parameters.
* @param params the parameter array (may be <code>null</code>)
*/
public PreparedStatementSetter newPreparedStatementSetter(Object[] params) {
return new PreparedStatementCreatorImpl(params != null ? Arrays.asList(params) : Collections.EMPTY_LIST);
}
/**
* Return a new PreparedStatementCreator for the given parameters.
* @param params list of parameters (may be <code>null</code>)
*/
public PreparedStatementCreator newPreparedStatementCreator(List params) {
return new PreparedStatementCreatorImpl(params != null ? params : Collections.EMPTY_LIST);
}
/**
* Return a new PreparedStatementCreator for the given parameters.
* @param params the parameter array (may be <code>null</code>)
*/
public PreparedStatementCreator newPreparedStatementCreator(Object[] params) {
return new PreparedStatementCreatorImpl(params != null ? Arrays.asList(params) : Collections.EMPTY_LIST);
}
/**
* Return a new PreparedStatementCreator for the given parameters.
* @param sqlToUse the actual SQL statement to use (if different from
* the factory's, for example because of named parameter expanding)
* @param params the parameter array (may be <code>null</code>)
*/
public PreparedStatementCreator newPreparedStatementCreator(String sqlToUse, Object[] params) {
return new PreparedStatementCreatorImpl(
sqlToUse, params != null ? Arrays.asList(params) : Collections.EMPTY_LIST);
}
/**
* PreparedStatementCreator implementation returned by this class.
*/
private class PreparedStatementCreatorImpl
implements PreparedStatementCreator, PreparedStatementSetter, SqlProvider, ParameterDisposer {
private final String actualSql;
private final List parameters;
public PreparedStatementCreatorImpl(List parameters) {
this(sql, parameters);
}
public PreparedStatementCreatorImpl(String actualSql, List parameters) {
this.actualSql = actualSql;
Assert.notNull(parameters, "Parameters List must not be null");
this.parameters = parameters;
if (this.parameters.size() != declaredParameters.size()) {
// account for named parameters being used multiple times
Set names = new HashSet();
for (int i = 0; i < parameters.size(); i++) {
Object o = parameters.get(i);
if (o instanceof SqlParameterValue) {
names.add(((SqlParameterValue)o).getName());
}
else {
names.add("Parameter #" + i);
}
}
if (names.size() != declaredParameters.size()) {
throw new InvalidDataAccessApiUsageException(
"SQL [" + sql + "]: given " + names.size() +
" parameters but expected " + declaredParameters.size());
}
}
}
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement ps = null;
if (generatedKeysColumnNames != null || returnGeneratedKeys) {
try {
if (generatedKeysColumnNames != null) {
ps = con.prepareStatement(this.actualSql, generatedKeysColumnNames);
}
else {
ps = con.prepareStatement(this.actualSql, PreparedStatement.RETURN_GENERATED_KEYS);
}
}
catch (AbstractMethodError ex) {
throw new InvalidDataAccessResourceUsageException(
"The JDBC driver is not compliant to JDBC 3.0 and thus " +
"does not support retrieval of auto-generated keys", ex);
}
}
else if (resultSetType == ResultSet.TYPE_FORWARD_ONLY && !updatableResults) {
ps = con.prepareStatement(this.actualSql);
}
else {
ps = con.prepareStatement(this.actualSql, resultSetType,
updatableResults ? ResultSet.CONCUR_UPDATABLE : ResultSet.CONCUR_READ_ONLY);
}
setValues(ps);
return ps;
}
public void setValues(PreparedStatement ps) throws SQLException {
// Determine PreparedStatement to pass to custom types.
PreparedStatement psToUse = ps;
if (nativeJdbcExtractor != null) {
psToUse = nativeJdbcExtractor.getNativePreparedStatement(ps);
}
// Set arguments: Does nothing if there are no parameters.
int sqlColIndx = 1;
for (int i = 0; i < this.parameters.size(); i++) {
Object in = this.parameters.get(i);
SqlParameter declaredParameter = null;
// SqlParameterValue overrides declared parameter metadata, in particular for
// independence from the declared parameter position in case of named parameters.
if (in instanceof SqlParameterValue) {
SqlParameterValue paramValue = (SqlParameterValue) in;
in = paramValue.getValue();
declaredParameter = paramValue;
}
else {
if (declaredParameters.size() <= i) {
throw new InvalidDataAccessApiUsageException(
"SQL [" + sql + "]: unable to access parameter number " + (i + 1) +
" given only " + declaredParameters.size() + " parameters");
}
declaredParameter = (SqlParameter) declaredParameters.get(i);
}
if (in instanceof Collection && declaredParameter.getSqlType() != Types.ARRAY) {
Collection entries = (Collection) in;
for (Iterator it = entries.iterator(); it.hasNext();) {
Object entry = it.next();
if (entry instanceof Object[]) {
Object[] valueArray = ((Object[])entry);
for (int k = 0; k < valueArray.length; k++) {
Object argValue = valueArray[k];
StatementCreatorUtils.setParameterValue(psToUse, sqlColIndx++, declaredParameter, argValue);
}
}
else {
StatementCreatorUtils.setParameterValue(psToUse, sqlColIndx++, declaredParameter, entry);
}
}
}
else {
StatementCreatorUtils.setParameterValue(psToUse, sqlColIndx++, declaredParameter, in);
}
}
}
public String getSql() {
return sql;
}
public void cleanupParameters() {
StatementCreatorUtils.cleanupParameters(this.parameters);
}
public String toString() {
StringBuffer buf = new StringBuffer("PreparedStatementCreatorFactory.PreparedStatementCreatorImpl: sql=[");
buf.append(sql).append("]; parameters=").append(this.parameters);
return buf.toString();
}
}
}
/*
* Copyright 2002-2007 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;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* General callback interface used by the {@link JdbcTemplate} class.
*
* <p>This interface sets values on a {@link java.sql.PreparedStatement} provided
* by the JdbcTemplate class, for each of a number of updates in a batch using the
* same SQL. Implementations are responsible for setting any necessary parameters.
* SQL with placeholders will already have been supplied.
*
* <p>It's easier to use this interface than {@link PreparedStatementCreator}:
* The JdbcTemplate will create the PreparedStatement, with the callback
* only being responsible for setting parameter values.
*
* <p>Implementations <i>do not</i> need to concern themselves with
* SQLExceptions that may be thrown from operations they attempt.
* The JdbcTemplate class will catch and handle SQLExceptions appropriately.
*
* @author Rod Johnson
* @since March 2, 2003
* @see JdbcTemplate#update(String, PreparedStatementSetter)
* @see JdbcTemplate#query(String, PreparedStatementSetter, ResultSetExtractor)
*/
public interface PreparedStatementSetter {
/**
* Set parameter values on the given PreparedStatement.
* @param ps the PreparedStatement to invoke setter methods on
* @throws SQLException if a SQLException is encountered
* (i.e. there is no need to catch SQLException)
*/
void setValues(PreparedStatement ps) throws SQLException;
}
/*
* Copyright 2002-2007 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;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.springframework.dao.DataAccessException;
/**
* Callback interface used by {@link JdbcTemplate}'s query methods.
* Implementations of this interface perform the actual work of extracting
* results from a {@link java.sql.ResultSet}, but don't need to worry
* about exception handling. {@link java.sql.SQLException SQLExceptions}
* will be caught and handled by the calling JdbcTemplate.
*
* <p>This interface is mainly used within the JDBC framework itself.
* A {@link RowMapper} is usually a simpler choice for ResultSet processing,
* mapping one result object per row instead of one result object for
* the entire ResultSet.
*
* <p>Note: In contrast to a {@link RowCallbackHandler}, a ResultSetExtractor
* object is typically stateless and thus reusable, as long as it doesn't
* access stateful resources (such as output streams when streaming LOB
* contents) or keep result state within the object.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since April 24, 2003
* @see JdbcTemplate
* @see RowCallbackHandler
* @see RowMapper
* @see org.springframework.jdbc.core.support.AbstractLobStreamingResultSetExtractor
*/
public interface ResultSetExtractor {
/**
* Implementations must implement this method to process the entire ResultSet.
* @param rs ResultSet to extract data from. Implementations should
* not close this: it will be closed by the calling JdbcTemplate.
* @return an arbitrary result object, or <code>null</code> if none
* (the extractor will typically be stateful in the latter case).
* @throws SQLException if a SQLException is encountered getting column
* values or navigating (that is, there's no need to catch SQLException)
* @throws DataAccessException in case of custom exceptions
*/
Object extractData(ResultSet rs) throws SQLException, DataAccessException;
}
/*
* Copyright 2002-2007 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;
/**
* Common base class for ResultSet-supporting SqlParameters like
* {@link SqlOutParameter} and {@link SqlReturnResultSet}.
*
* @author Juergen Hoeller
* @since 1.0.2
*/
public class ResultSetSupportingSqlParameter extends SqlParameter {
private ResultSetExtractor resultSetExtractor;
private RowCallbackHandler rowCallbackHandler;
private RowMapper rowMapper;
/**
* Create a new ResultSetSupportingSqlParameter.
* @param name name of the parameter, as used in input and output maps
* @param sqlType SQL type of the parameter according to java.sql.Types
*/
public ResultSetSupportingSqlParameter(String name, int sqlType) {
super(name, sqlType);
}
/**
* Create a new ResultSetSupportingSqlParameter.
* @param name name of the parameter, as used in input and output maps
* @param sqlType SQL type of the parameter according to java.sql.Types
* @param scale the number of digits after the decimal point
* (for DECIMAL and NUMERIC types)
*/
public ResultSetSupportingSqlParameter(String name, int sqlType, int scale) {
super(name, sqlType, scale);
}
/**
* Create a new ResultSetSupportingSqlParameter.
* @param name name of the parameter, as used in input and output maps
* @param sqlType SQL type of the parameter according to java.sql.Types
* @param typeName the type name of the parameter (optional)
*/
public ResultSetSupportingSqlParameter(String name, int sqlType, String typeName) {
super(name, sqlType, typeName);
}
/**
* Create a new ResultSetSupportingSqlParameter.
* @param name name of the parameter, as used in input and output maps
* @param sqlType SQL type of the parameter according to java.sql.Types
* @param rse ResultSetExtractor to use for parsing the ResultSet
*/
public ResultSetSupportingSqlParameter(String name, int sqlType, ResultSetExtractor rse) {
super(name, sqlType);
this.resultSetExtractor = rse;
}
/**
* Create a new ResultSetSupportingSqlParameter.
* @param name name of the parameter, as used in input and output maps
* @param sqlType SQL type of the parameter according to java.sql.Types
* @param rch RowCallbackHandler to use for parsing the ResultSet
*/
public ResultSetSupportingSqlParameter(String name, int sqlType, RowCallbackHandler rch) {
super(name, sqlType);
this.rowCallbackHandler = rch;
}
/**
* Create a new ResultSetSupportingSqlParameter.
* @param name name of the parameter, as used in input and output maps
* @param sqlType SQL type of the parameter according to java.sql.Types
* @param rm RowMapper to use for parsing the ResultSet
*/
public ResultSetSupportingSqlParameter(String name, int sqlType, RowMapper rm) {
super(name, sqlType);
this.rowMapper = rm;
}
/**
* Does this parameter support a ResultSet, i.e. does it hold a
* ResultSetExtractor, RowCallbackHandler or RowMapper?
*/
public boolean isResultSetSupported() {
return (this.resultSetExtractor != null || this.rowCallbackHandler != null || this.rowMapper != null);
}
/**
* Return the ResultSetExtractor held by this parameter, if any.
*/
public ResultSetExtractor getResultSetExtractor() {
return resultSetExtractor;
}
/**
* Return the RowCallbackHandler held by this parameter, if any.
*/
public RowCallbackHandler getRowCallbackHandler() {
return this.rowCallbackHandler;
}
/**
* Return the RowMapper held by this parameter, if any.
*/
public RowMapper getRowMapper() {
return this.rowMapper;
}
/**
* <p>This implementation always returns <code>false</code>.
*/
public boolean isInputValueProvided() {
return false;
}
}
/*
* Copyright 2002-2007 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;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* An interface used by {@link JdbcTemplate} for processing rows of a
* {@link java.sql.ResultSet} on a per-row basis. Implementations of
* this interface perform the actual work of processing each row
* but don't need to worry about exception handling.
* {@link java.sql.SQLException SQLExceptions} will be caught and handled
* by the calling JdbcTemplate.
*
* <p>In contrast to a {@link ResultSetExtractor}, a RowCallbackHandler
* object is typically stateful: It keeps the result state within the
* object, to be available for later inspection. See
* {@link RowCountCallbackHandler} for a usage example.
*
* <p>Consider using a {@link RowMapper} instead if you need to map
* exactly one result object per row, assembling them into a List.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see JdbcTemplate
* @see RowMapper
* @see ResultSetExtractor
* @see RowCountCallbackHandler
*/
public interface RowCallbackHandler {
/**
* Implementations must implement this method to process each row of data
* in the ResultSet. This method should not call <code>next()</code> on
* the ResultSet; it is only supposed to extract values of the current row.
* <p>Exactly what the implementation chooses to do is up to it:
* A trivial implementation might simply count rows, while another
* implementation might build an XML document.
* @param rs the ResultSet to process (pre-initialized for the current row)
* @throws SQLException if a SQLException is encountered getting
* column values (that is, there's no need to catch SQLException)
*/
void processRow(ResultSet rs) throws SQLException;
}
/*
* Copyright 2002-2007 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;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* An interface used by {@link JdbcTemplate} for mapping rows of a
* {@link java.sql.ResultSet} on a per-row basis. Implementations of this
* interface perform the actual work of mapping each row to a result object,
* but don't need to worry about exception handling.
* {@link java.sql.SQLException SQLExceptions} will be caught and handled
* by the calling JdbcTemplate.
*
* <p>Typically used either for {@link JdbcTemplate}'s query methods
* or for out parameters of stored procedures. RowMapper objects are
* typically stateless and thus reusable; they are an ideal choice for
* implementing row-mapping logic in a single place.
*
* <p>Alternatively, consider subclassing
* {@link org.springframework.jdbc.object.MappingSqlQuery} from the
* <code>jdbc.object</code> package: Instead of working with separate
* JdbcTemplate and RowMapper objects, you can build executable query
* objects (containing row-mapping logic) in that style.
*
* @author Thomas Risberg
* @author Juergen Hoeller
* @see JdbcTemplate
* @see RowCallbackHandler
* @see ResultSetExtractor
* @see org.springframework.jdbc.object.MappingSqlQuery
*/
public interface RowMapper {
/**
* Implementations must implement this method to map each row of data
* in the ResultSet. This method should not call <code>next()</code> on
* the ResultSet; it is only supposed to map values of the current row.
* @param rs the ResultSet to map (pre-initialized for the current row)
* @param rowNum the number of the current row
* @return the result object for the current row
* @throws SQLException if a SQLException is encountered getting
* column values (that is, there's no need to catch SQLException)
*/
Object mapRow(ResultSet rs, int rowNum) throws SQLException;
}
\ No newline at end of file
/*
* Copyright 2002-2005 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;
/**
* Interface to be implemented by objects that can provide SQL strings.
*
* <p>Typically implemented by PreparedStatementCreators, CallableStatementCreators
* and StatementCallbacks that want to expose the SQL they use to create their
* statements, to allow for better contextual information in case of exceptions.
*
* @author Juergen Hoeller
* @since 16.03.2004
* @see PreparedStatementCreator
* @see CallableStatementCreator
* @see StatementCallback
*/
public interface SqlProvider {
/**
* Return the SQL string for this object, i.e.
* typically the SQL used for creating statements.
* @return the SQL string, or <code>null</code>
*/
String getSql();
}
<html>
<body>
Context metadata abstraction for the configuration and execution of a stored procedure call.
</body>
</html>
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册