Mybatis-Plus调用PG Sql存储过程

梁修贤
2023-12-01

使用Mybatis-Plus调用pgsql存储过程两种方法

1.使用@Select注解

使用方法:在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方法支持传递数组

2.使用call关键字

使用场景1:只传递常规参数(如:Integer,String,Double…)

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 >

使用场景2:入参中有数组

使用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.不要忘了写下划线,否则形参类型就变成了普通类型!

 类似资料: