springframework.jdbc.object.StoredProcedure是对应存储过程调用的操作对象,它通过其父类org.springframework.jdbc.object.SqlCall获得相应的底层API支持(CallableStatementCreator),然后在此基础之上构建了调用存储过程的执行方法。
StoredProcedure是抽象类,所以需要实现相应子类以封装对特定存储过程的调用,还记得我们在讲解JdbcTemplate调用存储过程时候定义的存储过程吗?
CREATE PROCEDURE CountTable(IN tableName varchar(1000),OUT sqlStr varchar(1000) , INOUT v INT)
BEGIN
set @flag = v;
set @sql = CONCAT('select count(*) into @res from ' , tableName , ' where ACTIVE_FLAG=?');
PREPARE stmt FROM @sql;
EXECUTE stmt using @flag;
DEALLOCATE PREPARE stmt;
set v = @res;
set sqlStr = @sql;
END
通过继承StoredProcedure,我们可以为该存储过程的调用提供一个对应的操作对象:
public class CountTableStoredProcedure extends StoredProcedure {
private static final String PROCEDURE_NAME = "CountTable";
public static final String IN_PARAMETER_NAME = "tableName";
public static final String OUT_PARAMETER_NAME = "sqlStr";
public static final String INOUT_PARAMETER_NAME = "v";
public CountTableStoredProcedure(DataSource dataSource)
{
super(dataSource,PROCEDURE_NAME);
// setFunction(true);
declareParameter(new SqlParameter(IN_PARAMETER_NAME,Types.VARCHAR));
declareParameter(new SqlOutParameter(OUT_PARAMETER_NAME,Types.VARCHAR));
declareParameter(new SqlInOutParameter(INOUT_PARAMETER_NAME,Types.INTEGER));
compile();
}
public CountTableResult doCountTable(String tableName,Integer v)
{
Map paraMap = new HashMap();
paraMap.put(IN_PARAMETER_NAME, tableName);
paraMap.put(INOUT_PARAMETER_NAME, v);
Map resultMap = execute(paraMap);
CountTableResult result = new CountTableResult();
result.setSql((String)resultMap.get(OUT_PARAMETER_NAME));
result.setCount((Integer)resultMap.get(INOUT_PARAMETER_NAME));
return result;
}
}
关于该存储过程操作对象,部分细节我们有必要关注一下:
存储过程操作对象对应的SQL是存储过程的名称,而不是真正意义上的SQL语句,当我们调用compile方法的时候,StoredProcedure的父类SqlCall会根据你提供的存储过程名称拼装真正意义上的符合SQL92标准的存储过程调用语句,类似于“{ call CountTable(?,?,?) }”的形式。
因为我们的CountTableStoredProcedure只针对CountTable存储过程调用,所以,该存储过程的名称我们在类一开始就声明为常量:
private static final String PROCEDURE_NAME = "CountTable";
如果有多个存储过程的参数顺序相同,结果处理也一样的话,你也可以将存储过程的名称声明为变量,这完全要取决于具体的应用场景。
在构造方法中,我们将“setFunction(true);”注释掉了,因为我们调用的CountTable不是一个Function,如果你要调用的存储过程类型为Function的话,你需要通过该方法将“function”的值设置为true,以告知StoredProcedure在处理调用的时候要区别对待。
在complie之前通过declareParameter声明参数,这几乎是雷打不动的惯例,不过,在StoredProcedure中使用declareParameter的时候却要有所注意了: