簡體   English   中英

從 java 調用 Postgres 存儲過程,要返回的表

[英]Postgres stored procedure call from java, table to return

我做了一個 Postgres 存儲過程:

CREATE OR REPLACE FUNCTION GetUser(ipUserId integer)
RETURNS setof users AS $$
BEGIN
  IF ipUserId is null THEN
    return query select * from users A order by modifieddate desc;
  END IF;
  return query select * from users where iduser = ipUserId;
END;
$$ LANGUAGE plpgsql;

我嘗試在 java 中使用它,如下所示:

    StoredProcedureQuery query = entityManager.createStoredProcedureQuery("GetUser").
            registerStoredProcedureParameter("ipUserId",
                    Integer.class, ParameterMode.IN)
            .registerStoredProcedureParameter("users",
                    List.class, ParameterMode.OUT)
            .setParameter("postId", 1);

或者

 StoredProcedureQuery query = entityManager.createStoredProcedureQuery("GetUser")
                .registerStoredProcedureParameter(1,void.class, ParameterMode.REF_CURSOR)
                .registerStoredProcedureParameter(2,Integer.class, ParameterMode.IN)
                .setParameter(2, ipIdUser);

我想將結果存儲在列表中。

我應該怎么做,因為我遇到了各種各樣的錯誤?

更新:

這些是錯誤:

javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: Error calling CallableStatement.getMoreResults
Caused by: org.hibernate.exception.SQLGrammarException: Error calling CallableStatement.getMoreResults
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:106)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:111)
    at org.hibernate.result.internal.OutputsImpl.convert(OutputsImpl.java:79)
    at org.hibernate.result.internal.OutputsImpl.<init>(OutputsImpl.java:56)
    at org.hibernate.procedure.internal.ProcedureOutputsImpl.<init>(ProcedureOutputsImpl.java:34)
    at org.hibernate.procedure.internal.ProcedureCallImpl.buildOutputs(ProcedureCallImpl.java:453)
    at org.hibernate.procedure.internal.ProcedureCallImpl.getOutputs(ProcedureCallImpl.java:404)
    at org.hibernate.procedure.internal.ProcedureCallImpl.outputs(ProcedureCallImpl.java:663)
    at org.hibernate.procedure.internal.ProcedureCallImpl.getResultList(ProcedureCallImpl.java:751)
    ... 21 more
Caused by: org.postgresql.util.PSQLException: A CallableStatement was executed with an invalid number of parameters

您可以嘗試使用CallableStatement。 假設您的Connection變量正常:

CallableStatement stmt = con.prepareCall("{call SCHEMA.PROCEDURE_NAME (?, ?)}");
stmt.setInt(1, custom_var);
stmt.registerOutParameter(2, OracleTypes.INTEGER);
stmt.execute();

要獲得結果: stmt.getInt(3); stmt.getString(4) stmt.getInt(3); stmt.getString(4)

如果無法成功,請嘗試使用JdbcTemplate:

SimpleJdbcCall call = new SimpleJdbcCall(this.jdbcTemplate).withSchemaName(SCHEMA).withProcedureName(PROC);
MapSqlParameterSource params = new MapSqlParameterSource();
params.addValue("ipUserId", custom_var);
Map out = call.execute(params);

要獲取單個結果: Integer.parseInt("" + out.get("OUT_PARAM_NAME")); (String) out.get("OUT_PARAM_NAME2")); Integer.parseInt("" + out.get("OUT_PARAM_NAME")); (String) out.get("OUT_PARAM_NAME2"));

或者,您可以將所有結果保存在列表中以供日后使用:

SimpleJdbcCall call = new SimpleJdbcCall(this.jdbcTemplate);
List<Map<String, Object>> rows = call.getJdbcTemplate().queryForList(PROC_STRING, new Object[] { param1, param2 });

我找到了一個非常簡單的解決方案,只需執行一個SQL查詢以使用hibernate調用該過程即可。

    String SqlString = "select * from GetUser({0})";

    if (ipIdUser == null )
        SqlString = MessageFormat.format(SqlString, "NULL");
    else
        SqlString = MessageFormat.format(SqlString, ipIdUser);

    LOGGER.info("SqlSting =" + SqlString);

    return entityManager.createNativeQuery(SqlString, User.class)
            .getResultList();

為什么不對StoredProcedureQuery使用getResultList 這避免了必須進行字符串操作。

List<User> users = entityManager.createStoredProcedureQuery("GetUser")
  .registerStoredProcedureParameter("ipUserId", Integer.class, ParameterMode.IN)
  .setParameter("ipUserId", ipIdUser)
  .getResultList();

In your case, you have a table valued function that happens to map to an actual table, so the approach using the JPA native query is elegant too, but perhaps your projection is something different, or you return multiple nested data structures, arrays, etc ,使用 JPA 可能會很棘手。

jOOQ 為您的所有過程生成代碼,包括表值函數 例如,您將有一個包含getUser方法的Routines class,您可以像這樣查詢:

Result<GetUser> result = Routines.getUser(configuration, 1);

您還可以使用表值 function 作為查詢中的實際表,如下所示:

Result<GetUser> result = ctx.selectFrom(GETUSER(1)).fetch();

免責聲明:我在 jOOQ 背后的公司工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM