/*
* The Spring Framework is published under the terms
* of the Apache Software License.
*/
package org.springframework.jdbc.core;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
import org.springframework.jdbc.datasource.DataSourceUtils;
/**
* Utility class to use for JDBC queries from J2EE applications.
* This avoids the need for writing raw SQL.
*
* <p>Connections are obtained using JNDI data sources,
* so this class will only work within a J2EE application.
* It is probably best used from a stateless session bean; however
* it could also be used from within a web application.
*
* @author Rod Johnson
* @since May 30, 2001
*/
public class JdbcHelper {
/** Column extractor to use */
private ColumnExtractor columnExtractor;
private JdbcTemplate jdbcTemplate;
/**
* Create new JdbcHelper for the given DataSource.
* @param dataSource DataSource to use
*/
public JdbcHelper(DataSource dataSource) {
columnExtractor = new DefaultColumnExtractor();
jdbcTemplate = new JdbcTemplate(dataSource);
}
public JdbcTemplate getTemplate() {
return jdbcTemplate;
}
public int runSQLFunction(String sql) {
Integer I = (Integer) runSQLFunction(sql, Integer.class);
return I.intValue();
}
/**
* Run the given SQL function.
* @param sql SQL function, such as SELECT MAX(USER_ID) FROM USERS.
* Must return only one row.
* @param requiredType the class we need to extract the function result as.
* @throws org.springframework.dao.DataAccessException if there is a problem executing the function
*/
public Object runSQLFunction(final String sql, final Class requiredType) throws DataAccessException {
return runSQLFunction(sql, requiredType, null, null);
}
public int runSQLFunction(String sql, int[] types, Object[] args) {
Integer I = (Integer) runSQLFunction(sql, Integer.class, types, args);
return I.intValue();
}
public Object runSQLFunction(final String sql, final Class requiredType, int[] types, Object[] args) throws DataAccessException {
FunctionHandler fh = new FunctionHandler(sql, requiredType);
PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sql, types);
PreparedStatementCreator psc = pscf.newPreparedStatementCreator(args);
jdbcTemplate.query(psc, fh);
return fh.getFunctionValue();
}
/**
* Run the given SQL SELECT to return a ResultSet of an array of IDs.
* @param sql SQL function, such as SELECT MAX(USER_ID) FROM USERS.
* Must return only one row.
* @param params prepared statement parameters
* @throws org.springframework.dao.DataAccessException if there is a problem executing the function
*/
public int[] getIDs(final String sql, final Object[] params) throws DataAccessException {
Object[] os = getIDs(sql, Integer.class, params);
int[] is = new int[os.length];
for (int i = 0; i < is.length; i++)
is[i] = ((Integer) os[i]).intValue();
return is;
}
/**
* Run the given SQL SELECT to return a ResultSet of an array of IDs.
* @param sql SQL function, such as SELECT MAX(USER_ID) FROM USERS.
* Must return only one row.
* @param requiredType the class we need to extract the results as
* @param params prepared statement parameters
* @throws org.springframework.dao.DataAccessException if there is a problem executing the function
*/
public Object[] getIDs(final String sql, final Class requiredType, final Object[] params) throws DataAccessException {
class IDsHandler extends RowCountCallbackHandler implements PreparedStatementCreator, SqlProvider {
private List l = new LinkedList();
public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
PreparedStatement ps = conn.prepareStatement(sql);
DataSourceUtils.applyTransactionTimeout(ps, jdbcTemplate.getDataSource());
// Don't prepare if no params
if (params != null)
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
return ps;
}
public String getSql() {
return sql;
}
protected void processRow(ResultSet rs, int rowNum) throws SQLException {
l.add(columnExtractor.extractColumn(1, requiredType, rs));
}
public Object[] getIDs() {
return l.toArray();
}
}
IDsHandler idsh = new IDsHandler();
jdbcTemplate.query(idsh, idsh);
return idsh.getIDs();
}
private class FunctionHandler extends RowCountCallbackHandler {
private Object obj;
private Class requiredType;
private String sql;
public FunctionHandler(String sql, Class requiredType) {
this.requiredType = requiredType;
this.sql = sql;
}
/**
* This method is invoked for each row.
* @param rowNum number of the current row (starting from 0)
*/
protected void processRow(ResultSet rs, int rowNum) throws SQLException {
if (rowNum > 0)
throw new InvalidDataAccessResourceUsageException("runSQLFunction retrieved more than one row for sql [" + sql + "]: probably not a valid SQL function");
obj = columnExtractor.extractColumn(1, requiredType, rs);
}
public Object getFunctionValue() {
return obj;
}
}
}