使用方法:在dao层接口上加@Select注解,括号写 select +调存储过程名。
语法:
select 存储过程名( #{column1}, #{column2} …)
注意:
1.有入参时,@Selec注解中的参数名要和接口@Param注解里的参数名一致。
2.如果要调的存储过程没有入参就不用传参数
例:
@Select("select funName(#{column1},#{column2}...)")
Object funName(@Param("column1") String column1,@Param("column2") Integer column2...);
注意:
1).@Select注解里的参数顺序和接口里的参数顺序要保持一致。
2).使用@Select注解的方式有局限性,当需要给存储过程传入数组时,使用注解的方式会报错,原因是mybatis默认提供的类型转换器会失效,这时需要自定义一个类型转换器,并使用call关键字调用存储过程,call方法支持传递数组。
1.定义dao层接口,就像你平时做的一样,只不过参数需要放入map中
void funName(Map<String,Object> paramsMap);
2.编写mapper,其中“mode=IN”语句是固定的,表示参数是输入参数。
<select id="funName" parameterType="java.util.HashMap" statementType="CALLABLE">
{ call funName(#{column1,mode=IN},#{column2,mode=IN}...) }
</select >
使用call关键字调用存储过程并传递数组时,需要先自定义一个类作为类型处理器,实现 org.apache.ibatis.type.TypeHandler 接口, 或继承org.apache.ibatis.type.BaseTypeHandler, 再将该类指定到call中,就可以将数组映射到一个 JDBC 类型。
1.自定义ArrayTypeHandler类型处理器,继承TypeHandler接口:
代码:
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.TypeException;
import java.sql.*;
/**
* @Description 自定义类型转换器
* 当mybatis调用存储过程传入了数组类型的入参时,mybatis提供的默认类型转换器会失效,此时需要自定义一个类型转换器
* 数组类型目前仅针对类中定义的有效:Integer[],String[], Boolean[],Double[]
* @Date 2021/8/17 15:41
* @Created by LSH
*/
@MappedJdbcTypes(JdbcType.ARRAY)
public class ArrayTypeHandler extends BaseTypeHandler<Object[]> {
private static final String TYPE_NAME_VARCHAR = "varchar";
private static final String TYPE_NAME_INTEGER = "integer";
private static final String TYPE_NAME_BOOLEAN = "boolean";
private static final String TYPE_NAME_NUMERIC = "numeric";
@Override
public void setNonNullParameter(PreparedStatement ps, int i,
Object[] parameter, JdbcType jdbcType) throws SQLException {
String typeName = null;
if (parameter instanceof Integer[]) {
typeName = TYPE_NAME_INTEGER;
} else if (parameter instanceof String[]) {
typeName = TYPE_NAME_VARCHAR;
} else if (parameter instanceof Boolean[]) {
typeName = TYPE_NAME_BOOLEAN;
} else if (parameter instanceof Double[]) {
typeName = TYPE_NAME_NUMERIC;
}
if (typeName == null) {
throw new TypeException( "ArrayTypeHandler parameter typeName error, your type is " + parameter.getClass().getName());
}
Connection conn = ps.getConnection();
Array array = conn.createArrayOf(typeName, parameter);
ps.setArray(i, array);
}
@Override
public Object[] getNullableResult(ResultSet rs, String columnName)
throws SQLException {
return getArray(rs.getArray(columnName));
}
@Override
public Object[] getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
return getArray(rs.getArray(columnIndex));
}
@Override
public Object[] getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
return getArray(cs.getArray(columnIndex));
}
private Object[] getArray(Array array) {
if (array == null) {
return null;
}
try {
return (Object[]) array.getArray();
} catch (Exception e) {
}
return null;
}
}
2.定义dao层接口,就像你平时做的一样,只不过参数需要放入map中
void funName(Map<String,Object> paramsMap);
3.编写mapper,其中“mode=IN”语句是固定的,表示参数是输入参数。然后在数组参数的“mode=IN”后指定typeHandler,写上自定义的那个类型转换器全路径。
<select id="funName" parameterType="java.util.HashMap" statementType="CALLABLE">
{ call funName(#{column1,mode=IN},#{column2,mode=IN},#{column3,mode=IN,typeHandler=com.geohey.dao.handler.ArrayTypeHandler}...) }
</select>
4.pgsql 带有数组参数的存储过程的形参写法
CREATE OR REPLACE FUNCTION funName(column1 int4,column2 varchar,column3 _varchar)
RETURNS "pg_catalog"."void" AS $BODY$
DECLARE
pro1 type;-- pro1为自定义变量名,type为变量类型,可以是integer,varchar,record等。
···
BEGIN
pro1 :=XXX;-- 在存储过程中给变量赋值,不要直接等于,格式是冒号+等号,即“:=”
-- To Do Something...
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100
注意:
1.入参是数组且为整数数组时,形参类型是:_int4;
2.入参是数组且为字符串数组时,形参类型是:_varchar;
3.不要忘了写下划线,否则形参类型就变成了普通类型!