【问题标题】:Returning two user define type object from stored procedure and calling stored procedure at repository level using spring-data-jpa从存储过程返回两个用户定义类型对象并使用 spring-data-jpa 在存储库级别调用存储过程
【发布时间】:2020-03-24 02:10:01
【问题描述】:

我有一个如下定义的存储过程:

PROCEDURE TestABC (tableName IN VARCHAR2, cardID IN VARCHAR2, detail OUT UserDefineObjectA, td OUT UserDefineObjectB);

UserDefineObjectAUserDefineObjectB 都是用户定义的对象,并且都具有相同的字段,除了两个对象都应该从过程中返回。返回这两个对象背后有一些业务。

我用@Repository 注释写了方法类,它有以下方法。我正在使用来自spring-data -jpa@Procedure 注释。当前实现@Procedure 只能采用一个outputParameterName。但就我而言,我除了返回两个用户定义类型的对象。

@Procedure(procedureName = "TestABC" , outputParameterName = "{UserDefineObjectA, UserDefineObjectB}")
public List<Object[]> getAllDetails(@Param("tableName") String tableName, @Param("cardID ") String cardID);

然后,我尝试了使用@NamedStoredProcedureQuery 的不同方法。但问题在于这种方法是我必须将所有这些查询写入实体标签,这会增加更多复杂性。我必须创建一个实体并编写所有存储过程并调用存储库,如下例所示:

how to get user-defined SQL procedure out parameter from java class

有没有更好的方法可以解决这个问题?我可以在我的类中的方法级别写@NamedStoredProcedureQuery,它被注释为@Repository

我正在尝试实现的遗留代码示例。

    callableStatement = connection.prepareCall("{call ABC(?,?,?,?)}");

      callableStatement.setString(1, "test");
      callableStatement.setString(2, "12345679090978");

      callableStatement.registerOutParameter(3, Types.ARRAY, AConstants.UserDefineObjectA);
      callableStatement.registerOutParameter(4, Types.STRUCT, AConstants.UserDefineObjectB);

      callableStatement.execute();
      return (Object[]) ((java.sql.Array) callableStatement.getObject(3)).getArray();

【问题讨论】:

    标签: java stored-procedures spring-data-jpa


    【解决方案1】:

    我认为有两种方法可以解决这个问题。

    1.更新 Spring Data JPA 版本

    自 Spring Data JPA 2.2-RC1 起支持多个输出参数。
    https://spring.io/blog/2019/06/17/spring-data-moore-rc1-and-lovelace-sr9-released
    https://jira.spring.io/browse/DATAJPA-707

    接口方法只需要有一个 Map 返回类型,所以每个输出参数都可以通过键名访问:

    /**
     * Explicitly mapped to named stored procedure "User.plus1IOoptional" in {@link EntityManager}. 
     * Returns 2 out params
     * as a Map, second one amoung which is null.
    */
    @Procedure(name = "User.plus1IOoptional") // DATAJPA-1579
    Map<String, Integer> entityAnnotatedCustomNamedProcedurePlus1IOoptional(@Param("arg") Integer arg);
    

    More samples on Github

    2.直接使用JPA API,通过稍微复杂一点

    StoredProcedureQuery proc = em.createNamedStoredProcedureQuery("plus1");
    
    proc.setParameter("arg", 1);
    proc.execute();
    Integer res1 = (Integer) proc.getOutputParameterValue("res1");
    Integer res2 = (Integer) proc.getOutputParameterValue("res2");
    

    我希望它会有所帮助。

    【讨论】:

    • 所以,我必须返回一个类型为 Map。但我的存储过程将 4 个字段作为输入除外。会不会有什么问题?我除了可以通过键名访问的 Map 类型。更新了我想要实现的旧代码。
    • 您的旧代码似乎使用 JDCB 来调用该过程。
      我更喜欢使用 jpa 目录。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-10-19
    • 2015-12-26
    • 1970-01-01
    • 2017-07-20
    • 2021-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多