0
Follow
0
View

Mybatis call database stored procedure, parameters how to dynamically submit according to the parameters in the database stored procedure

eaw2008 注册会员
2023-02-27 11:22

GP-based solutions
You can use Mybatis dynamic SQL to dynamically generate statements that call stored procedures. Specifically, you can use the Mybatis foreach tag and choose tag to dynamically generate the arguments that call the stored procedure. Here is an example:

1. First, query the parameters of the stored procedure. The Mybatis select tag is used to execute the query, and the query results are stored in a List.

<select id="getProcedureParams" resultType="hashmap">
  SELECT parameter_name, data_type, parameter_mode
  FROM sys.sp_procedure_params_100_managed
  WHERE procedure_name = #{procedureName}
select>



2.在调用存储过程的时候,使用foreach标签和choose标签来动态生成参数列表。这里使用foreach标签遍历上一步查询到的参数列表,并使用choose标签根据参数的mode属性来判断是IN参数还是OUT参数。

```bash
<select id="callProcedure" statementType="CALLABLE">
  {call bsp_CommRole;8(
    <foreach collection="params" item="param" separator=",">
      
        <when test="param.parameter_mode == 'IN'">
          #{param.parameter_name, mode=IN, jdbcType=param.data_type}
        when>
        <when test="param.parameter_mode == 'OUT'">
          #{param.parameter_name, mode=OUT, jdbcType=param.data_type}
        when>
      
    foreach>
  )}
select>


3. Invoke the SQL statement in the Java code and pass the query result as a parameter.

<select id="callProcedure" statementType="CALLABLE">
  {call bsp_CommRole;8(
    <foreach collection="params" item="param" separator=",">
      <choose>
        <when test="param.parameter_mode == 'IN'">
          #{param.parameter_name, mode=IN, jdbcType=param.data_type}
        when>
        <when test="param.parameter_mode == 'OUT'">
          #{param.parameter_name, mode=OUT, jdbcType=param.data_type}
        when>
      choose>
    foreach>
  )}
select>


This allows you to dynamically generate statements calling the stored procedure based on the latest stored procedure parameter information. Note that the dynamic SQL feature of Mybatis is used here, and there is no need to modify the code or redistribute the application.

crispenn 注册会员
2023-02-27 11:22

This answer quotes ChatGPT

Please reply me if you have any questions

Depending on your requirements, you need to get the latest parameter fields and input/output types before calling the stored procedure, and pass them dynamically to the mapper.xml file in MyBatis for calling the stored procedure.

This can be done through the following steps:

1. Create a Java class that connects to the database using JDBC and invokes the stored procedure [sys].[sp_procedure_params_100_managed] to obtain the latest parameter fields and their input and output types.

2. In the Java class, the obtained parameter information is dynamically constructed into a Map object containing the parameter name, input/output types, and parameter values. You can use a HashMap or other type of Map to store parameter information.

3. Pass the above Map object to the mapper.xml file in MyBatis. The dynamic SQL statement construction tool provided by MyBatis can be used to dynamically construct SQL statements calling stored procedures in mapper.xml file. For example, you can use labels to traverse parameters in a Map object and dynamically build call statements for stored procedures.

4. Call MyBatis mapper interface in Java code, pass the above dynamically constructed SQL statement to MyBatis mapper method as parameters, then the stored procedure can be executed and the result obtained.

Below is an example Java class that demonstrates how to connect to a database using JDBC and invoke stored procedures [sys].[sp_procedure_params_100_managed], retrieve the latest parameter fields and their input and output types, and build them dynamically as a Map object.

import java.sql.*;
import java.util.*;

public class ProcedureParamMapper {
    private static final String URL = "jdbc:sqlserver://localhost:1433;databaseName=MyDatabase";
    private static final String USERNAME = "myuser";
    private static final String PASSWORD = "mypassword";
    
    public Map getProcedureParams(String procedureName) throws SQLException {
        Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
        Map paramInfo = new HashMap<>();
        try {
            CallableStatement statement = connection.prepareCall("{call [sys].[sp_procedure_params_100_managed](?)}");
            statement.setString(1, procedureName);
            ResultSet resultSet = statement.executeQuery();
            while (resultSet.next()) {
                String paramName = resultSet.getString("parameter_name");
                int paramMode = resultSet.getInt("parameter_mode");
                int dataType = resultSet.getInt("data_type");
                String typeName = resultSet.getString("type_name");
                paramInfo.put(paramName, getJdbcType(paramMode, dataType, typeName));
            }
        } finally {
            connection.close();
        }
        return paramInfo;
    }
    
    private int getJdbcType(int paramMode, int dataType, String typeName) {
        switch (paramMode) {
            case 1: return Types.IN;
            case 2: return Types.OUT;
            case 3: return Types.INOUT;
            default: return Types.NULL;
        }
    }
}


In MyBatis mapper.xml file, you can use tags to traverse the parameter information obtained above and dynamically construct SQL statements that call stored procedures. For example:



<select id="callProcedure" statementType="CALLABLE">
    { call ${procedureName}(
    <foreach collection="params" item="param" separator=",">
        #{param.value, mode=IN, jdbcType=param.type}
    foreach>
) }
    select>


In the above example, tags are used to traverse all parameters in the params parameter Map object and dynamically build the call statement of the stored procedure. ${procedureName} indicates the name of the invoked stored procedure, #{param.value} indicates the value of the current parameter, and the mode and jdbcType attributes specify the input/output type and JDBC type of the parameters, respectively. You can adjust these parameters according to your actual requirements.

Finally, the callProcedure method of MyBatis mapper interface is called in Java code, and the above dynamic constructed SQL statement is passed to the method as a parameter, then the stored procedure can be executed and the result can be obtained. For example:


SqlSession sqlSession = sqlSessionFactory.openSession();
try {
    ProcedureParamMapper mapper = sqlSession.getMapper(ProcedureParamMapper.class);
    Map<String, Object> params = mapper.getProcedureParams("bsp_CommRole");
    Map<String, Object> inputParams = new HashMap<>();
    inputParams.put("action", "someAction");
    inputParams.put("lan_id", 1);
    inputParams.put("branch_id", "someBranchId");
    Map<String, Object> outputParams = new HashMap<>();
    outputParams.put("column_title", null);
    outputParams.put("column_length", null);
    outputParams.put("column_align", null);
    Map<String, Object> result = new HashMap<>();
    result.putAll(inputParams);
    result.putAll(outputParams);
    sqlSession.selectOne("callProcedure", new HashMap<String, Object>() {{
        put("procedureName", "bsp_CommRole");
        put("params", result);
    }});
    System.out.println("output parameters: " + outputParams);
} finally {
    sqlSession.close();
}


In the preceding example, the getProcedureParams method that appears in the ProcedureParamMapper is invoked to obtain the latest parameter information of the stored procedure, and the input and output parameters are stored in inputParams and outputParams Map objects, respectively. It then merges inputParams and outputParams into a result Map object and passes the procedureName and result objects as parameters to the callProcedure method. Finally, the output parameter results of the stored procedure are obtained from the outputParams Map object.

dgzhengming 注册会员
2023-02-27 11:22

Refer to GPT and my own idea, according to your description, you need to dynamically adjust the parameters of Mybatis call stored procedure, to adapt to the modification of stored procedure parameters. The following provides a solution based on Mybatis custom TypeHandler.

First, you need to write a custom TypeHandler that converts the parameters and types of stored procedures to the parameter types and modes of Mybatis. Here is an example TypeHandler:

public class StoredProcedureTypeHandler extends BaseTypeHandler> {
    
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, List parameter, JdbcType jdbcType) throws SQLException {
        StringBuilder sb = new StringBuilder();
        sb.append("{call ").append(parameter.get(0).getName()).append("(");
        for (int j = 1; j < parameter.size(); j++) {
            sb.append("?,");
        }
        sb.deleteCharAt(sb.length() - 1).append(")}");
        ps.setString(i, sb.toString());
    }

    @Override
    public List getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return parseStoredProcedureParams(rs.getString(columnName));
    }

    @Override
    public List getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return parseStoredProcedureParams(rs.getString(columnIndex));
    }

    @Override
    public List getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return parseStoredProcedureParams(cs.getString(columnIndex));
    }

    private List parseStoredProcedureParams(String paramStr) {
        // 解析存储过程参数
        // ...
    }
}

This TypeHandler converts the name and argument list of the stored procedure into the string format required by Mybatis to call the stored procedure and sets it as the arguments of the PreparedStatement. In addition, it converts the stored procedure parameter string returned by a ResultSet into a Java object. You need to achieve parseStoredProcedureParams method according to actual situation.

Next, you need to register the TypeHandler in the Mybatis configuration file:


    ="com.example.StoredProcedureTypeHandler" javaType="java.util.List" jdbcType="VARCHAR"/>

In the Mapper XML file, you need to declare a select statement that returns type List to query the list of parameters for the stored procedure:

<select id="getStoredProcedureParams" resultType="java.util.List">
    SELECT param_name, param_type, param_mode
    FROM [sys].[sp_procedure_params_100_managed]
    WHERE procedure_name = #{procedureName}
    ORDER BY param_order;
select>

Finally, in Java code, you can query the list of stored procedure parameters using the selectOne method of SqlSession, which is then passed as a parameter to the Mybatis calling stored procedure method. Here is an example:

SqlSession sqlSession = sqlSessionFactory.openSession();
try {
    List params = sqlSession.selectOne("com.example.MyMapper.getStoredProcedureParams", "存储过程名");
    Map paramValues = new HashMap<>();
    for (StoredProcedureParam param : params) {
        if (param.getMode() == StoredProcedureParam.Mode.IN) {
            paramValues.put(param.getName(), /* 从请求参数中获取对应的值 */);
} else {
paramValues.put(param.getName(), null);
// 输出参数需要预先设为 null,否则会抛出异常
}
}
sqlSession.selectOne("com.example.MyMapper.callStoredProcedure", new StoredProcedureCall("存储过程名", paramValues));

// 处理输出参数
for (StoredProcedureParam param : params) {
    if (param.getMode() == StoredProcedureParam.Mode.OUT) {
        System.out.println(param.getName() + ": " + paramValues.get(param.getName()));
    }
}
} finally {
sqlSession.close();
}

Where, "Com. Example. MyMapper. GetStoredProcedureParams" and "com. Example. MyMapper. CallStoredProcedure" are two MyBatis Mapper method, Their SQL queries and calls need to be defined in the corresponding Mapper XML file. The getStoredProcedureParams method returns parameter information about the specified stored procedure, and the callStoredProcedure method invokes the specified stored procedure.

In the getStoredProcedureParams method, you can use the metadata function of the database to obtain parameter information about a specified stored procedure. For example, for an Oracle database, you can use the following SQL query:

SELECT
argument_name AS name,
data_type AS type,
IN_OUT AS mode
FROM
all_arguments
WHERE
object_name = #{procedureName}
ORDER BY
position;

This query returns the parameter information of the stored procedure, including the parameter name, parameter type, and parameter mode(input or output). You can map this information to Java objects using functions such as resultMap and resultType in MyBatis.

In the callStoredProcedure method, you can use MyBatis selectOne or update methods to execute the stored procedure call. For example, for an Oracle database, you can call a stored procedure with the following statement:

BEGIN
Name of the stored procedure(:param1, :param2,... , :paramN);
END;

where :param1, :param2,... , :paramN indicates a parameter of a stored procedure. It must correspond to the parameter name queried in the getStoredProcedureParams method. BEGIN and END are used here to encapsulate the stored procedure call, because in Oracle, stored procedure calls must be encapsulated in BEGIN and END.

After calling the stored procedure, you can take the value of the output parameter from paramValues and process it accordingly. Note that the output parameter needs to be pre-set to null, otherwise an exception will be thrown.

djboy001 注册会员
2023-02-27 11:22

Little witch referred to bing and GPT part of the content write :
Mybatis call database stored procedure, parameters dynamic submit method has many, the following describes a way to achieve.

First, in Mybatis, tags can be used to dynamically submit parameters. You can dynamically pass the parameters in the list collection into the call by defining a list collection in the mapper.xml file and then traversing the list collection using tags.

Specific implementation steps are as follows:

  1. First obtain the latest parameter and the order of the parameter through the stored procedure;
  2. then define a list collection in the mapper.xml file, putting the latest arguments and order into the list collection;
  3. Finally uses the tag to iterate over the list collection when calling the stored procedure, passing the parameters from the list collection into the call dynamically.

Example:

<select id="callProcedure" parameterType="map" statementType="CALLABLE">
    {call bsp_CommRole(
        <foreach collection="paramList" item="item" index="index" open="" separator="," close="">
            #{item.paramName, mode = #{item.paramMode}, jdbcType = #{item.jdbcType}}
        foreach>)}
select>

The above is an implementation way of dynamic submission according to the latest parameters of the database stored procedure when Mybatis calls the database stored procedure.
The answer is not easy, so take it.