【问题标题】:How to call a stored procedure in Hibernate?如何在 Hibernate 中调用存储过程?
【发布时间】:2011-06-11 02:16:02
【问题描述】:

我在 Oracle 数据库中有一个存储过程。

GET_VENDOR_STATUS_COUNT(DOCUMENT_ID IN NUMBER, NOT_INVITED OUT NUMBER, INVITE_WITHDRAWN OUT NUMBER, ...

其他参数为OUT参数。

在我的 hbm 文件中,我写了以下内容:

<sql-query name="getVendorStatus" callable="true">
     <return-scalar column="NOT_INVITED" type="string"/>
     <return-scalar column="INVITE_WITHDRAWN" type="string"/>
     <return-scalar column="INVITED" type="string"/>
     <return-scalar column="DISQUALIFIED" type="string"/>
     <return-scalar column="RESPONSE_AWAITED" type="string"/>
     <return-scalar column="RESPONSE_IN_PROGRESS" type="string"/>
     <return-scalar column="RESPONSE_RECEIVED" type="string"/>
     { call GET_VENDOR_STATUS_COUNT(:DOCUMENT_ID , :NOT_INVITED ,:INVITE_WITHDRAWN ,:INVITED ,:DISQUALIFIED ,:RESPONSE_AWAITED ,:RESPONSE_IN_PROGRESS ,:RESPONSE_RECEIVED ) }
</sql-query>

这是我的 Java 代码:

 session.getNamedQuery("getVendorStatus").setParameter("DOCUMENT_ID", "DOCUMENT_ID").setParameter("NOT_INVITED", "NOT_INVITED") 

...继续直到所有参数。

我收到以下 SQL 异常:

18:29:33,056 WARN [JDBCExceptionReporter] SQL 错误:1006,SQLState: 72000
18:29:33,056 错误 [JDBCExceptionReporter] ORA-01006:绑定 变量不存在


请让我知道在 Hibernate 中调用存储过程的确切过程是什么?我不想使用 JDBC 可调用语句。

【问题讨论】:

标签: java oracle hibernate stored-procedures


【解决方案1】:

4.1 不支持您正在尝试的内容(INOUT/OUT 参数处理)。通过 4.1 Hibernate 的可调用语句支持侧重于 ResultSet 返回。上游主服务器上已经支持您正在尝试的内容,并将成为 Hibernate 下一个主要版本(将是 4.2 或 5.0)的一部分;在那里,调用函数/过程现在是一流的操作。

目前,您必须直接使用 JDBC 或从 master 构建 Hibernate 并使用新的支持。如果你选择后者,它看起来像:

StoredProcedureCall call = session.createStoredProcedureCall( "GET_VENDOR_STATUS_COUNT" )
        .registerStoredProcedureParameter( "DOCUMENT_ID", Long.class, ParameterMode.IN )
        .registerStoredProcedureParameter( "NOT_INVITED", String.class, ParameterMode.OUT )
        ...;
call.getRegisteredParameter( "DOCUMENT_ID" ).bindValue( theDocumentId );
StoredProcedureOutputs outputs = call.getOutputs();
String notInvited = (String) outputs.getOutputParameterValue( "NOT_INVITED" );
...

该代码还很年轻,很可能会发生变化。例如,当我更频繁地编写这些示例时,我认为应该将registerStoredProcedureParameter 重命名为registerParameterdeclareParameter,并且它应该返回声明/注册的类型表示;类似:

interface RegisteredParameter<T> {
    Class<T> getParameterType();
    // only valid for IN or INOUT params
    void bindValue(T value);
}

<T> RegisteredParameter<T> registerParameter(String name, Class<T> type, ParameterMode mode);

这将允许:

StoredProcedureCall call = session.createStoredProcedureCall( "GET_VENDOR_STATUS_COUNT" )
call.registerParameter( "DOCUMENT_ID", Long.class, ParameterMode.IN ).bindValue( theDocumentId );
RegisteredParameter<String> notInvitedParam = call.registerParameter( "NOT_INVITED", String.class, ParameterMode.OUT );
...
String notInvited = outputs.getOutputParameterValue( notInvitedParam );

作为额外的奖励,早期尝试此功能的人可以帮助在它发布之前塑造它的外观(此时更改要困难得多)。

【讨论】:

  • 当我说当前不支持 INOUT/OUT 参数处理时,我应该澄清一下。实际上,您可以有 INOUT/OUT 参数,它们只需要返回 ResultSets,并且每次调用只能有一个参数返回结果。
  • 感谢您在答案中提供的信息,似乎上述功能在最新的休眠版本(4.3.6)上可用。当存储过程返回一个结果集时,它可以完美运行,但是多个结果集存在问题,请您指出上述功能文档的 URL。我在谷歌上找不到。
【解决方案2】:

使用 Hibernate,您必须应用一个结果类来将 SP 结果转换为,并且返回的列的名称必须别名为结果类中正确的返回字段。 Hibernate 希望 SQLServer 存储过程有一个返回结果,并且它想知道要创建什么样的对象。在我工作的地方,我们通常返回两列的单行结果:return_code 和 message。

例如...

  • return_code = 404, message = "找不到页面"

  • return_code = 200,消息 =“OK”

该类的映射与任何其他 POJO 一样,只要确保使其可序列化即可。例如:

@Entity
public class StoredProc implements Serializable {

  private Integer returnCode;
  private String message;

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "return_code", nullable = false, unique = true)
  public Integer getReturnCode() {
    return returnCode;
  }
  public void setReturnCode(Integer returnCode) {
    this.returnCode = returnCode;
  }

  @Column(name = "message")
  public String getMessage() {
    return message;
  }
  public void setMessage(String message) {
    this.message = message;
  }

}

我似乎还记得关于 Hibernate 使用的命名约定的一些一般性的矫揉造作。例如,我认为 names_with_underscores 被翻译成 camelCaseFieldNames。

【讨论】:

    猜你喜欢
    • 2011-04-10
    • 2012-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-25
    • 2023-03-20
    • 1970-01-01
    相关资源
    最近更新 更多