Можно ли вызвать хранимые процедуры sql server 2008 с помощью Hibernate Query? - PullRequest
1 голос
/ 16 апреля 2011

Я пытаюсь вызвать хранимую процедуру, используя класс запросов Hibernate:

Query q = ssn.createSQLQuery("{ ? = call SEARCH_RESULT(?,?,?) }");

int idx = 0;
q.setParameter(idx, sc.getId(), StandardBasicTypes.INTEGER); 
q.setString(++idx, sc.getNum() == null ? null : sc.getNum()
        .toString()); // second parameter
q.setString(++idx, sc.getName());
List list = q.list();

Но это дает следующее исключение, хотя 4-го параметра нет: Запросить полезные предложения и потенциальное решение.

com.microsoft.sqlserver.jdbc.SQLServerException: The value is not set for the parameter number 4.
    com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(SQLServerException.java:171)
    com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.buildParamTypeDefinitions(SQLServerPreparedStatement.java:262)
    com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.buildPreparedStrings(SQLServerPreparedStatement.java:221)
    com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doPrepExec(SQLServerPreparedStatement.java:598)
    com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:386)
    com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:340)
    com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:4575)
    com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1400)
    com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:179)
    com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:154)
    com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeQuery(SQLServerPreparedStatement.java:283)
    org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
    org.hibernate.loader.Loader.getResultSet(Loader.java:1953)
    org.hibernate.loader.Loader.doQuery(Loader.java:802)
    org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
    org.hibernate.loader.Loader.doList(Loader.java:2533)
    org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276)
    org.hibernate.loader.Loader.list(Loader.java:2271)
    org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:316)
    org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1842)
    org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165)
    org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:157)

Ответы [ 2 ]

1 голос
/ 16 апреля 2011

Я думаю, что есть 4 параметра

Query q = ssn.createSQLQuery("{ ? = call SEARCH_RESULT(?,?,?) }");

Имеется 4 знака вопроса, один из которых является выходным параметром, и 3 входных параметра. Или 1 возврат и 3 входа?

Не уверен в NHibernate, никогда не использовал его для выполнения хранимых процедур, но похоже, что вы говорите NHibernate ожидать 4 парма и только 3.

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

Hibernate не знает, к какому объекту конвертировать результат вашей хранимой процедуры. Я обычно указываю один код / ​​значение возврата для всех моих SP, затем проверяю соответствие полей результирующего класса с одинаковыми именами псевдонимов столбцов в моем результате возврата SP.

Например ...

{ call my_function(:param1, :param2) }

return_code = 404, message = "Page not found"

return_code = 200, message = "OK"

Класс отображается как любой другой POJO, просто убедитесь, что он сериализуем. Я использую что-то вроде этого:

@NamedNativeQueries({
  @NamedNativeQuery(name = "myFunction",
                  query = "{ call my_function(:param1, :param2) }",
                  resultClass = StoredProc.class)
})
@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;
  }

}

Обратите внимание на небольшую разницу в том, как я называю свои сохраненные процессы - я не использую стиль назначения "{? = Call my_function (?,?)}", А вместо этого использую прямую "{call my_function (: param1) ,: param2)} ". В моем коде я определяю эти SP с помощью @NamedNativeQuery аннотаций и заключаю их в аннотацию @NamedNativeQueries (множественное число!) И прикрепляю их к своему классу StoredProc. Таким образом, все в нужном месте ... красиво и аккуратно.

Когда я хочу вызвать один из них из кода, это очень просто:

(StoredProc) getSession().getNamedQuery("myFunction")
                         .setParameter("param1", value)
                         .setParameter("param2", value2)
                         .uniqueResult();

Красиво и просто. И если SP выдает какие-либо ошибки, я получаю их в ответном сообщении, которое затем могу обработать так, как мне нравится (автоматическая отправка отчета об ошибке, отправка сообщения в пользовательский интерфейс и т. Д.)

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