SimpleJdbcCall中的多个输出参数

时间:2018-06-06 06:34:35

标签: java spring spring-boot spring-jdbc

在Java spring boot框架中,尝试使用以下方法使用Store过程

 jdbcTemplate.setDataSource(dataSource);

       SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate).withSchemaName("abc").withFunctionName("proname").addDeclaredParameter(new
 SqlOutParameter("",""));
        Map<String, Object> map= new HashMap<>();
         map.put("a",a);
        map.put("b",b);
        map.put("c",c);
        map.put("d",d);

 SqlParameterSource in = new MapSqlParameterSource(map);
 Map<String, Object> out = simpleJdbcCall.execute(in);

但我的程序也有参数这里是我的程序

function proname(z varchar2,
                                            a varchar2,
                                            b varchar2,
                                            c varchar2,
                                            d in out number,
                                            e out number,
                                            f out varchar2,
                                            g out varchar2)

程序也有参数,如上面的代码所示,问题是如何在简单JDBC调用中提及多个输出参数(注意多个)?

5 个答案:

答案 0 :(得分:1)

您可以按照以下教程接受存储过程中的多个out参数。这应该简要介绍一下如何实现:

  1. Spring JDBC with Stored Procedures
  2. Spring JDBC with Simple JDBC Call
  3. 从上面的文章中获取示例代码,这就是您调用执行存储过程的方式:

    SimpleJdbcCall jdbcCall = new SimpleJdbcCall(dataSource).withProcedureName("getRecord");
    SqlParameterSource in = new MapSqlParameterSource().addValue("in_id", id);
    Map<String, Object> out = jdbcCall.execute(in);
    

    在同一个示例中,一旦获得所需的输出,您将以此格式从响应中获取OUT个参数:

    Student student = new Student();
    student.setId(id);
    student.setName((String) out.get("out_name"));
    student.setAge((Integer) out.get("out_age"));
    

    希望这有帮助!

答案 1 :(得分:1)

我尝试过以下操作,并且可以正常工作:

jdbcTemplate.execute((CallableStatementCreator) con -> {
        con = con.unwrap(OracleConnection.class);
        CallableStatement cs = con.prepareCall("{ ? = call usr.abc.proname(?,?,?,?,?,?,?) }");
        cs.registerOutParameter(1, OracleType.NUMBER);
        cs.setString(2, "a");
        cs.setString(3, "b");
        cs.setString(4, "c");
        cs.registerOutParameter(4, OracleType.NUMBER);
        cs.registerOutParameter(5, OracleType.NUMBER);
        cs.registerOutParameter(6, OracleType.VARCHAR);
        cs.registerOutParameter(7, OracleType.VARCHAR);
        return cs;
    }, (CallableStatementCallback<MyModel>) cs -> {
        cs.execute();
        return new MyModel(cs.getInt(1),
                           cs.getInt(4),
                           cs.getInt(5),
                           cs.getString(6),
                           cs.getString(7));
    });

答案 2 :(得分:0)

您可以使用SimpleJdbcCall的declareParameters方法,例如:

.declareParameters(
                            new SqlParameter("in_id", Types.NUMERIC),
                            new SqlOutParameter("out_first_name", Types.VARCHAR),
                            new SqlOutParameter("out_last_name", Types.VARCHAR),
                            new SqlOutParameter("out_birth_date", Types.DATE)
                    );

答案 3 :(得分:0)

您可以这样做:

   SimpleJdbcCall call = new SimpleJdbcCall(jdbcTemplate).withFunctionName("PRONAME")

                .declareParameters(
                        new SqlParameter("z", Types.VARCHAR),
                        new SqlParameter("a", Types.VARCHAR),
                        new SqlParameter("b", Types.VARCHAR),
                        new SqlParameter("c", Types.VARCHAR),
                        new SqlInOutParameter("d", Types.NUMERIC),
                        new SqlOutParameter("e", Types.NUMERIC),
                        new SqlOutParameter("f", Types.VARCHAR),
                        new SqlOutParameter("g", Types.VARCHAR)
                );


        Map<String, Object> result = call.execute("z", "a", "b", "c", 7);
        System.out.println(result);

结果:

{return=test, d=5, e=6, f=b, g=c}

这是函数:

create function proname(z varchar2,
                                            a varchar2,
                                            b varchar2,
                                            c varchar2,
                                            d in out number,
                                            e out number,
                                            f out varchar2,
                                            g out varchar2)
                                            return varchar2 is
begin
 d:=5;
 e:=6;
 f:='b';
 g:='c';  

return 'test';
end;

注意:按照.declareParameters参数的顺序,类型和方向必须与db函数的参数匹配。

答案 4 :(得分:0)

您还可以使用morejdbc(在maven central中可用),它方便且类型安全。您的通话将如下所示:

import static org.morejdbc.SqlTypes.*;
import static org.morejdbc.NamedJdbcCall.call;
import org.morejdbc.*;
...
private JdbcTemplate jdbcTemplate;
...
Out<Integer> outD = Out.of(INTEGER);
Out<Long> outE = Out.of(LONG);
Out<String> oufF = Out.of(VARCHAR);
Out<String> outG = Out.of(VARCHAR);
jdbcTemplate.execute(call("proname")
    .in("a", a)
    .in("b", b)
    .in("c", c)
    .in("z", z)
    .inOut("d", d, outD)
    .out("e", outE)
    .out("f", outF)
    .out("g", outG));

System.out.println("d=" + outD.get() + ", e=" + outE.get() + ", f=" + outF.get() + ", g=" + outG.get());

如果您有用于输入/输出参数的POJO,则它可能更加简洁,例如

@lombok.Data // generates getters, setters, toString
public class ProData {
    private int a;
    private int b;
    private int c;
    private int z;
    private int d;
    private long e;
    private String f;
    private String g;
}
...
ProData data = ...;

jdbcTemplate.execute(call("proname")
    .in("a", data.getA())
    .in("b", data.getB())
    .in("c", data.getC())
    .in("z", data.getZ())
    .inOut("d", data.getD(), data::setD)
    .out("e", LONG, data::setE)
    .out("f", VARCHAR, data::setF)
    .out("g", VARCHAR, data::setG));

System.out.println("Data: " + data);

请注意,对于函数,调用不应为call("proname"),而应为call("proname", VARCHAR)(您未声明函数结果类型)。通话应该看起来像

String result = jdbcTemplate.execute(call("proname", VARCHAR)
    .in("a", data.getA())
    .in("b", data.getB())
    .in("c", data.getC())
    .in("z", data.getZ())
    .inOut("d", data.getD(), data::setD)
    .out("e", LONG, data::setE)
    .out("f", VARCHAR, data::setF)
    .out("g", VARCHAR, data::setG));