📄 jdbctemplate.java
字号:
},
new ObjectResultSetExtractor(requiredType));
}
public long queryForLong(String sql, final Object[] args) throws DataAccessException {
Number number = (Number) queryForObject(sql, args, Number.class);
return (number != null ? number.longValue() : 0);
}
public int queryForInt(String sql, final Object[] args) throws DataAccessException {
Number number = (Number) queryForObject(sql, args, Number.class);
return (number != null ? number.intValue() : 0);
}
protected int update(PreparedStatementCreator psc, final PreparedStatementSetter pss) throws DataAccessException {
if (logger.isDebugEnabled()) {
logger.debug("Executing SQL update using PreparedStatementCreator [" + psc + "]");
}
Integer result = (Integer) execute(psc, new PreparedStatementCallback() {
public Object doInPreparedStatement(PreparedStatement ps) throws SQLException {
if (pss != null) {
pss.setValues(ps);
}
int rows = ps.executeUpdate();
if (logger.isDebugEnabled()) {
logger.debug("SQL update affected " + rows + " rows");
}
return new Integer(rows);
}
});
return result.intValue();
}
public int update(PreparedStatementCreator psc) throws DataAccessException {
return update(psc, null);
}
public int update(String sql, final PreparedStatementSetter pss) throws DataAccessException {
return update(new SimplePreparedStatementCreator(sql), pss);
}
public int update(String sql, final Object[] args, final int[] argTypes) throws DataAccessException {
return update(sql, new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
if (args != null) {
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i], argTypes[i]);
}
}
}
});
}
public int update(String sql, final Object[] args) throws DataAccessException {
return update(sql, new PreparedStatementSetter() {
public void setValues(PreparedStatement ps) throws SQLException {
if (args != null) {
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
}
}
});
}
public int[] batchUpdate(String sql, final BatchPreparedStatementSetter pss) throws DataAccessException {
return (int[]) execute(sql, new PreparedStatementCallback() {
public Object doInPreparedStatement(PreparedStatement ps) throws SQLException {
int batchSize = pss.getBatchSize();
if (ps.getConnection().getMetaData().supportsBatchUpdates()) {
for (int i = 0; i < batchSize; i++) {
pss.setValues(ps, i);
ps.addBatch();
}
return ps.executeBatch();
}
else {
int[] rowsAffected = new int[batchSize];
for (int i = 0; i < batchSize; i++) {
pss.setValues(ps, i);
rowsAffected[i] = ps.executeUpdate();
}
return rowsAffected;
}
}
});
}
//-------------------------------------------------------------------------
// Methods dealing with callable statements
//-------------------------------------------------------------------------
public Object execute(CallableStatementCreator csc, CallableStatementCallback action) {
Connection con = DataSourceUtils.getConnection(getDataSource());
CallableStatement cs = null;
try {
Connection conToUse = con;
if (this.nativeJdbcExtractor != null &&
this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeCallableStatements()) {
conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
}
cs = csc.createCallableStatement(conToUse);
DataSourceUtils.applyTransactionTimeout(cs, getDataSource());
CallableStatement csToUse = cs;
if (nativeJdbcExtractor != null) {
csToUse = nativeJdbcExtractor.getNativeCallableStatement(cs);
}
Object result = action.doInCallableStatement(csToUse);
SQLWarning warning = cs.getWarnings();
throwExceptionOnWarningIfNotIgnoringWarnings(warning);
return result;
}
catch (SQLException ex) {
throw getExceptionTranslator().translate("executing CallableStatementCallback [" + csc + "]",
getSql(csc), ex);
}
finally {
JdbcUtils.closeStatement(cs);
DataSourceUtils.closeConnectionIfNecessary(con, getDataSource());
}
}
public Object execute(final String callString, CallableStatementCallback action) {
return execute(new SimpleCallableStatementCreator(callString), action);
}
public Map call(CallableStatementCreator csc, final List declaredParameters) throws DataAccessException {
if (logger.isDebugEnabled()) {
logger.debug("Executing call using CallableStatementCreator [" + csc + "]");
}
return (Map) execute(csc, new CallableStatementCallback() {
public Object doInCallableStatement(CallableStatement cs) throws SQLException {
boolean retVal = cs.execute();
if (logger.isDebugEnabled()) {
logger.debug("CallableStatement.execute returned [" + retVal + "]");
}
Map retMap = new HashMap();
if (retVal) {
retMap.putAll(extractReturnedResultSets(cs, declaredParameters));
}
retMap.putAll(extractOutputParameters(cs, declaredParameters));
return retMap;
}
});
}
/**
* Extract output parameters from the completed stored procedure.
* @param cs JDBC wrapper for the stored procedure
* @param parameters parameter list for the stored procedure
* @return parameters to the stored procedure
*/
protected Map extractOutputParameters(CallableStatement cs, List parameters) throws SQLException {
Map outParams = new HashMap();
int sqlColIndex = 1;
for (int i = 0; i < parameters.size(); i++) {
SqlParameter param = (SqlParameter) parameters.get(i);
if (param instanceof SqlOutParameter) {
SqlOutParameter outParam = (SqlOutParameter) param;
Object out = cs.getObject(sqlColIndex);
if (out instanceof ResultSet) {
ResultSet outRs = (ResultSet) out;
ResultSet rsToUse = outRs;
if (this.nativeJdbcExtractor != null) {
rsToUse = this.nativeJdbcExtractor.getNativeResultSet(rsToUse);
}
// we can't pass back a ResultSet since the connection will be closed - we must process it
try {
if (outParam.isResultSetSupported()) {
RowCallbackHandler rch = null;
if (outParam.isRowMapperSupported()) {
rch = outParam.newResultReader();
}
else {
rch = outParam.getRowCallbackHandler();
}
(new RowCallbackHandlerResultSetExtractor(rch)).extractData(rsToUse);
logger.debug("ResultSet returned from stored procedure was processed");
if (outParam.isRowMapperSupported()) {
outParams.put(param.getName(), ((ResultReader) rch).getResults());
}
else {
outParams.put(param.getName(), "ResultSet processed.");
}
}
else {
logger.warn("ResultSet returned from stored procedure but a corresponding SqlOutParameter with a RowCallbackHandler was not declared");
outParams.put(param.getName(), "ResultSet was returned but not processed.");
}
}
finally {
JdbcUtils.closeResultSet(outRs);
}
}
else {
outParams.put(param.getName(), out);
}
}
if (!(param instanceof SqlReturnResultSet)) {
sqlColIndex++;
}
}
return outParams;
}
/**
* Extract returned resultsets from the completed stored procedure.
* @param cs JDBC wrapper for the stored procedure
* @param parameters Parameter list for the stored procedure
*/
protected Map extractReturnedResultSets(CallableStatement cs, List parameters) throws SQLException {
Map returnedResults = new HashMap();
int rsIndex = 0;
do {
SqlParameter param = null;
if (parameters != null && parameters.size() > rsIndex) {
param = (SqlParameter) parameters.get(rsIndex);
}
if (param instanceof SqlReturnResultSet) {
SqlReturnResultSet rsParam = (SqlReturnResultSet) param;
ResultSet rs = cs.getResultSet();
try {
ResultSet rsToUse = rs;
if (this.nativeJdbcExtractor != null) {
rsToUse = this.nativeJdbcExtractor.getNativeResultSet(rs);
}
RowCallbackHandler rch = null;
if (rsParam.isRowMapperSupported()) {
rch = rsParam.newResultReader();
}
else {
rch = rsParam.getRowCallbackHandler();
}
(new RowCallbackHandlerResultSetExtractor(rch)).extractData(rsToUse);
if (rsParam.isRowMapperSupported()) {
returnedResults.put(param.getName(), ((ResultReader) rch).getResults());
}
else {
returnedResults.put(param.getName(), "ResultSet returned from stored procedure was processed");
}
}
finally {
JdbcUtils.closeResultSet(rs);
}
}
else {
logger.warn("ResultSet returned from stored procedure but a corresponding SqlReturnResultSet parameter was not declared");
}
rsIndex++;
}
while (cs.getMoreResults());
return returnedResults;
}
/**
* Throw an SQLWarningException if we're not ignoring warnings.
* @param warning warning from current statement. May be null,
* in which case this method does nothing.
*/
protected void throwExceptionOnWarningIfNotIgnoringWarnings(SQLWarning warning) throws SQLWarningException {
if (warning != null) {
if (this.ignoreWarnings) {
logger.warn("SQLWarning ignored: " + warning);
}
else {
throw new SQLWarningException("Warning not ignored", warning);
}
}
}
/**
* Determine SQL from potential provider object.
* @param sqlProvider object that's potentially a SqlProvider
* @return the SQL string, or null
* @see SqlProvider
*/
protected String getSql(Object sqlProvider) {
if (sqlProvider instanceof SqlProvider) {
return ((SqlProvider) sqlProvider).getSql();
}
else {
return null;
}
}
/**
* Simple adapter for PreparedStatementCreator, allowing to use a plain SQL statement.
*/
protected static final class SimplePreparedStatementCreator
implements PreparedStatementCreator, SqlProvider {
private final String sql;
public SimplePreparedStatementCreator(String sql) {
this.sql = sql;
}
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
return con.prepareStatement(this.sql);
}
public String getSql() {
return sql;
}
}
/**
* Simple adapter for CallableStatementCreator, allowing to use a plain SQL statement.
*/
protected static final class SimpleCallableStatementCreator
implements CallableStatementCreator, SqlProvider {
private final String callString;
public SimpleCallableStatementCreator(String callString) {
this.callString = callString;
}
public CallableStatement createCallableStatement(Connection con) throws SQLException {
return con.prepareCall(this.callString);
}
public String getSql() {
return callString;
}
}
/**
* Adapter to enable use of a RowCallbackHandler inside a ResultSetExtractor.
* <p>Uses a regular ResultSet, so we have to be careful when using it:
* We don't use it for navigating since this could lead to unpredictable consequences.
*/
protected static final class RowCallbackHandlerResultSetExtractor implements ResultSetExtractor {
private final RowCallbackHandler rch;
public RowCallbackHandlerResultSetExtractor(RowCallbackHandler rch) {
this.rch = rch;
}
public Object extractData(ResultSet rs) throws SQLException {
while (rs.next()) {
this.rch.processRow(rs);
}
if (this.rch instanceof ResultReader) {
return ((ResultReader) this.rch).getResults();
}
else {
return null;
}
}
}
/**
* ResultSetExtractor implementation that returns an ArrayList of HashMaps.
*/
protected static final class ListResultSetExtractor implements ResultSetExtractor {
public Object extractData(ResultSet rs) throws SQLException {
ResultSetMetaData rsmd = rs.getMetaData();
int numberOfColumns = rsmd.getColumnCount();
List listOfRows = new ArrayList();
while (rs.next()) {
Map mapOfColValues = new HashMap(numberOfColumns);
for (int i = 1; i <= numberOfColumns; i++) {
mapOfColValues.put(rsmd.getColumnName(i), rs.getObject(i));
}
listOfRows.add(mapOfColValues);
}
return listOfRows;
}
}
/**
* ResultSetExtractor implementation that returns single result object.
*/
protected static final class ObjectResultSetExtractor implements ResultSetExtractor {
private final Class requiredType;
public ObjectResultSetExtractor(Class requiredType) {
this.requiredType = requiredType;
}
public Object extractData(ResultSet rs) throws SQLException {
ResultSetMetaData rsmd = rs.getMetaData();
int nrOfColumns = rsmd.getColumnCount();
if (nrOfColumns != 1) {
throw new InvalidDataAccessApiUsageException("Expected single column, but received " + nrOfColumns + " columns");
}
if (!rs.next()) {
throw new InvalidDataAccessApiUsageException("Expected single row, not empty ResultSet");
}
Object result = rs.getObject(1);
if (rs.next()) {
throw new InvalidDataAccessApiUsageException("Expected single row, not more than one");
}
if (result != null && this.requiredType != null && !this.requiredType.isInstance(result)) {
throw new InvalidDataAccessApiUsageException("Result object (db-type=\"" + rsmd.getColumnTypeName(1) +
"\" value=\"" + result + "\") is of type [" +
rsmd.getColumnClassName(1) + "] and not of required type [" +
this.requiredType.getName() + "]");
}
return result;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -