如何在Hibernate中调用存储过程?

7

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

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

其他参数是输出参数。

在我的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,SQL状态: 72000
18:29:33,056 ERROR [JDBCExceptionReporter] ORA-01006:绑定变量不存在


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


请参考官方文档(http://docs.redhat.com/docs/en-US/JBoss_Enterprise_Web_Platform/5/html/Hibernate_Core_Reference_Guide/sp_query.html)了解使用存储过程的方法和限制,详情请点击此处(http://docs.redhat.com/docs/en-US/JBoss_Enterprise_Web_Platform/5/html/Hibernate_Core_Reference_Guide/sp_query.html)。 - Aravind Yarram
2个回答

5
您尝试的内容(INOUT/OUT参数处理)在4.1版本中不受支持。在4.1版本之前,Hibernate的可调用语句支持主要关注ResultSet返回。在上游主干已经支持您正在尝试的内容,并将成为Hibernate的下一个主要版本的一部分(该版本将是4.2或5.0)。在那里,调用函数/过程现在是一项一流的操作。
目前,您必须直接使用JDBC或从主干构建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,并且每次调用只能有一个参数返回结果。 - Steve Ebersole
感谢您在答案中提供的信息,最新的Hibernate版本(4.3.6)似乎具有上述功能。当存储过程返回一个结果集时,它可以完美地工作,但是当有多个结果集时会出现问题,请问您能否指出上述功能文档的URL?我在谷歌上找不到。 - Yasitha Waduge

1

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

例如...

  • return_code = 404,message =“页面未找到”

  • return_code = 200,message =“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使用的命名约定似乎存在一些普遍的不合理之处。例如,带下划线的名称将被翻译为camelCaseFieldNames。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接