Как вызвать хранимую процедуру в Hibernate? - PullRequest
7 голосов
/ 18 января 2011

У меня есть хранимая процедура в базе данных 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.

Ответы [ 2 ]

5 голосов
/ 16 ноября 2012

То, что вы пытаетесь (обработка параметров INOUT / OUT), не поддерживается в 4.1.В версии 4.1 поддержка вызываемых операторов Hibernate сосредоточена на возвратах ResultSet.Существует поддержка того, что вы пытаетесь уже использовать в основной ветке разработки, и будет частью следующего основного выпуска Hibernate (который будет либо 4.2, либо 5.0);здесь вызов функций / процедур теперь является операцией первого класса.

На данный момент вы должны либо использовать JDBC напрямую, либо собрать Hibernate из master и использовать эту новую поддержку.Если вы выберете более поздний вариант, он будет выглядеть следующим образом:

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 следует переименовать в registerParameter или declareParameter и что оно должно возвращать типизированное представление объявления / регистрации;что-то вроде:

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

В качестве дополнительного бонуса, люди, пробующие это раньше, получают помощь в формировании того, как это выглядит до его выпускав этот момент изменить намного сложнее).

1 голос
/ 01 февраля 2012

В Hibernate вам нужно применить класс результатов для преобразования результатов SP, а имена возвращаемых столбцов должны быть привязаны к правильным полям возврата в вашем классе результатов. Hibernate хочет, чтобы хранимые процессы SQLServer имели один возвращаемый результат, и он хочет знать, какой тип объекта создать. Где я работаю, мы обычно возвращаем один результат строки из двух столбцов: return_code и message.

Например ...

  • return_code = 404, message = "Страница не найдена"

  • код_возврата = 200, сообщение = "ОК"

Класс отображается как любой другой 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...