日期:2014-05-16  浏览次数:20475 次

使用JdbcTemplate调用数据库存储过程

      使用Jdbc调用存储过程相信大多数朋友在开发过程中都会用到,本例使用一个工具类将调用存储过程的方法封装起来,隐藏了大部分的处理逻辑,使用起来还是很方便的。


package com.coolfancy;

import java.math.BigDecimal;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.Date;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.List;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.stereotype.Service;

@Service
public class ProcedureUtil extends JdbcDaoSupport {

	@Autowired
	public void setter(DataSource dataSource) {
		super.setDataSource(dataSource);
	}

	/**
	 * <p>
	 * 调用存储过程。
	 * </p>
	 * <p>
	 * 输入参数可识别的数据类型为String、Long、BigDecimal和Date,识别三种特殊类型的入参:
	 * <ul>
	 * <li>"varcharnull"表示Null值的VARCHAR型入参;
	 * <li>"numbernull"表示Null值的Number型入参;
	 * <li>"datenull"表示Null值的Date型入参。
	 * </ul>
	 * </p>
	 * <p>
	 * 输出参数的类型用字符串表示,识别的三种值:
	 * <ul>
	 * <li>"varchar"表示VARCHAR型出参;
	 * <li>"number"表示Number型出参;
	 * <li>"date"表示Date型出参。
	 * </ul>
	 * </p>
	 * <p>
	 * 
	 * @author coolfancy
	 * @param proName
	 *            存储过程名称。
	 * @param paraIn
	 *            输入参数。
	 * @param _paraOutType
	 *            输出参数的类型,传入Null表示没有返回值。
	 * @return 存储过程的返回值。
	 */
	public List<Object> executeProcedure(final String proName, final Object[] paraIn, final String[] _paraOutType) {
		final int len = _paraOutType == null ? 0 : _paraOutType.length;
		final int[] paraOutType = new int[len];
		for (int i = 0; i < len; i++) {
			if ("varchar".equalsIgnoreCase(_paraOutType[i]))
				paraOutType[i] = Types.VARCHAR;
			else if ("number".equalsIgnoreCase(_paraOutType[i]))
				paraOutType[i] = Types.FLOAT;
			else if ("date".equalsIgnoreCase(_paraOutType[i]))
				paraOutType[i] = Types.DATE;
		}
		paraOutType[len] = Types.FLOAT;
		paraOutType[len + 1] = Types.VARCHAR;
		return  getJdbcTemplate().execute(new ConnectionCallback<List<Object>>() {
			public List<Object> doInConnection(Connection conn) throws SQLException, DataAccessException {
				final List<Object> returnObjs = new ArrayList<Object>();
				final StringBuffer procedureName = new StringBuffer("{call ").append(proName).append("(");
				for (int i = 0; i < paraIn.length + len; i++) {
					if (i == paraIn.length + len - 1)
						procedureName.append("?)}");
					else
						procedureName.append("?,");
				}
				final CallableStatement proc = conn.prepareCall(procedureName.toString());
				for (int i = 1; i <= paraIn.length; i++) {
					final Object para_obj = paraIn[i - 1];
					if (para_obj == null || para_obj.equals("varcharnull")) {
						proc.setNull(i, Types.VARCHAR);
					} else if (para_obj.equals("numbernull")) {
						proc.setNull(i, Types.FLOAT);
					} else if (para_obj.equals("datenull")) {
						proc.setNull(i, Types.DATE);
					} else if (para_obj instanceof String) {
						proc.setString(i, (String) para_obj);
					} else if (para_obj instanceof BigDecimal) {
						proc.setBigDecimal(i, (BigDecimal) para_obj);
					} else if (para_obj instanceof Date) {
						proc.setDate(i, (Date) para_obj);
					} else if (para_obj instanceof Long) {
						proc.setLong(i, ((Long) para_obj).longValue());
					} else {
						throw new RuntimeException("执行存储过程" + proName + "]时发生错误:");
					}
				}
				for (int i = paraIn.length + 1; i <= paraIn.length + paraOutType.length; i++)
					proc.re