简体   繁体   English

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

[英]How to call a stored procedure in Hibernate?

I have a stored procedure in Oracle database. 我在Oracle数据库中有一个存储过程。

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

Other parameters are OUT parameters. 其他参数是OUT参数。

In my hbm file I have written the following: 在我的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>

And here is my Java code: 这是我的Java代码:

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

... continue till all the parameters. ...继续直到所有参数。

I am getting the following SQL exception: 我收到以下SQL异常:

18:29:33,056 WARN [JDBCExceptionReporter] SQL Error: 1006, SQLState: 72000 18:29:33,056 WARN [JDBCExceptionReporter] SQL错误:1006,SQLState:72000
18:29:33,056 ERROR [JDBCExceptionReporter] ORA-01006: bind variable does not exist 18:29:33,056错误[JDBCExceptionReporter] ORA-01006:绑定变量不存在


Please let me know what is the exact process of calling a stored procedure in Hibernate? 请让我知道在Hibernate中调用存储过程的确切过程是什么? I do not want to use JDBC callable statement. 我不想使用JDBC可调用语句。

What you are trying (INOUT/OUT parameter handling) is not supported in 4.1. 4.1不支持您尝试的操作(INOUT / OUT参数处理)。 Through 4.1 Hibernate's callable statement support focuses on ResultSet returns. 通过4.1 Hibernate的可调用语句支持着重于ResultSet返回。 There is support for what you are trying already in place on upstream master and will be part of the next major release of Hibernate (which will be either 4.2 or 5.0); 上游母版已经支持您正在尝试的内容,并且将成为Hibernate的下一个主要版本(版本为4.2或5.0)的一部分; there, calling functions/procedures is now a first class operation. 在那里,调用函数/过程现在是一流的操作。

For now, you have to either use JDBC directly or build Hibernate from master and use that new support. 现在,您必须直接使用JDBC或通过master来构建Hibernate并使用该新支持。 If you opt for the later, it would look like: 如果选择后者,它将看起来像:

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" );
...

That code is still young and will likely change. 该代码还很年轻,可能会更改。 For example, as I write these examples more often I think that registerStoredProcedureParameter should be renamed as registerParameter or declareParameter and that it should return a typed representation of the declaration/registration; 例如,当我更频繁地编写这些示例时,我认为registerStoredProcedureParameter应该重命名为registerParameterdeclareParameter ,并且它应该返回声明/注册的类型化表示形式。 something like: 就像是:

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);

which would then allow: 这将允许:

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 );

As an added bonus, people trying this out early get to help shape what this looks like prior to it being released (at which point it is much harder to change). 另外一个好处是,尽早尝试此方法的人可以在发布它之前帮助塑造它的外观(此时很难更改)。

With Hibernate you have to apply a result class to transform the SP results to, and the names of the columns that return have to be aliased to the correct return fields in your result class. 使用Hibernate,您必须应用结果类将SP结果转换为结果,并且返回的列的名称必须别名为结果类中正确的返回字段。 Hibernate wants SQLServer stored procs to have a single return result and it wants to know what kind of Object to create. Hibernate希望SQLServer存储的proc具有单个返回结果,并且它想知道要创建哪种Object。 Where I work we usually return a single row result of two columns: return_code and message. 在我工作的地方,我们通常返回两列的单行结果:return_code和message。

For example... 例如...

  • return_code = 404, message = "Page not found" return_code = 404,消息=“找不到页面”

  • return_code = 200, message = "OK" return_code = 200,消息=“确定”

The class is mapped like any other POJO, just be sure to make it Serializeable. 像其他任何POJO一样映射该类,只需确保使其可序列化即可。 For example: 例如:

@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;
  }

}

I also seem to recall some general hokeyness with regard to the naming convention Hibernate uses. 我似乎还想起了有关Hibernate使用的命名约定的一些一般技巧。 I think names_with_underscores are translated to camelCaseFieldNames for instance. 例如,我认为names_with_underscores会转换为camelCaseFieldNames。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM