Spring Boot, JPA, @Query, хранимая процедура Sybase

#java #spring-boot #sybase

#java #весенняя загрузка #sybase

Вопрос:

Пытаюсь выполнить вызов хранимой процедуры Sybase с помощью JPA @Query. Я следил за информацией, представленной здесь, https://www.baeldung.com/spring-data-jpa-stored-procedures , в качестве ориентира, даже несмотря на то, что информация предназначена для MySQL и именованных параметров. Я знаю, что хранимая процедура работает, так как я могу выполнить ее с помощью клиента DBVis. Я также знаю, что значения хранимой процедуры верны, так как я включил ведение журнала в режиме гибернации и всегда вижу следующий фрагмент перед каждым вызовом :

 2020-12-30 13:51:07 TRACE o.h.t.d.sql.BasicBinder - binding parameter [1] as [VARCHAR] - [pub_req_t]
2020-12-30 13:51:07 TRACE o.h.t.d.sql.BasicBinder - binding parameter [2] as [INTEGER] - [1]
 

@Query выглядит следующим образом :

 @Query(value = "call rp_surrogate(?1, ?2);", nativeQuery = true)
int getSurrogateByQueryV1(String surrtype, Integer newsurr );
 

Объявление хранимой процедуры :

 CREATE PROCEDURE dbo.rp_surrogate (
    @surrtype       char(32),
    @newsurr        domn_num_id    output
)
as begin
 

Кажется, не имеет значения, что я передаю в параметр ?2 (output), так как он все равно игнорируется. Я пробовал как jconn4, версия 7.0, так и jtds, версия 1.3.1, драйверы JDBC…оба они создают одно и то же исключение :

  • jconn4 — Вызвано: com.sybase.jdbc4.jdbc.SybSQLException: неправильный синтаксис рядом с ‘@p0’.
  • jtds — Вызвано: java.sql.SQLException: неправильный синтаксис рядом с ‘@P0’.

Стек времени выполнения :

  • Пружинный ботинок 2.2.8
  • Java 1.8
  • Sybase ASE 15

Я пробовал использовать аннотацию @Modifying в сочетании с @Trasactional: думая, что JPA, возможно, будет использовать @P0 в качестве обновленных строк или кода состояния для хранимой процедуры … Нет.

 @Modifying
@Query(value = "call rp_surrogate(?1, ?2);", nativeQuery = true)
@Transactional(rollbackFor=Exception.class)
int getSurrogateByQueryV1(String surrtype, Integer newsurr );

Results in : Caused by: com.sybase.jdbc4.jdbc.SybSQLException: Incorrect syntax near '@p0'.
 

Кроме того, попробовал 4 варианта @Query, все возвращают одно и то же исключение…Некоторые с точкой с запятой, некоторые с вызовом.

 @Query(value = "call rp_surrogate(?1, ?2)", nativeQuery = true)
int getSurrogateByQueryV1(String surrtype, Integer newsurr );

Results in : Caused by: java.sql.SQLException: Incorrect syntax near '@P0'.

@Query(value = "call rp_surrogate(?1, ?2);", nativeQuery = true)
int getSurrogateByQueryV2(String surrtype, Integer newsurr );

Results in : Caused by: java.sql.SQLException: Incorrect syntax near '@P0'.

@Query(value = "rp_surrogate(?1, ?2);", nativeQuery = true)
int getSurrogateByQueryV3(String surrtype, Integer newsurr );

Results in : Caused by: java.sql.SQLException: Incorrect syntax near '@P0'.

@Query(value = "rp_surrogate(?1, ?2)", nativeQuery = true)
int getSurrogateByQueryV4(String surrtype, Integer newsurr );

Results in : Caused by: java.sql.SQLException: Incorrect syntax near '@P0'.
 

Единственное, что я могу сообщить, что работает, это следующее, которое работает, но мы хотели бы иметь чистую / бережливую версию с использованием @Query, поскольку некоторые из этих процедур, которые нам нужно вызвать, имеют довольно большие параметры.

 @Override
public int getSurrogateByType(String typeSurrogate) {
    EntityManager em = secondaryEntityManager.getObject().createEntityManager();

    StoredProcedureQuery query = em.createStoredProcedureQuery("rp_surrogate");
    // JDBC : The jconn and jtDS drivers do NOT understand named parameters...we
    // MUST use positional...
    //query.registerStoredProcedureParameter("surrtype",     String.class,     ParameterMode.IN    );
    //query.registerStoredProcedureParameter("newsurr",     Long.class,     ParameterMode.OUT    );
    query.registerStoredProcedureParameter(1, String.class,     ParameterMode.IN);
    query.registerStoredProcedureParameter(2, Integer.class,    ParameterMode.OUT);
    getLog().error("getSurrogateByType() - Surrogate Type [{}]", typeSurrogate);
    query.setParameter(1, typeSurrogate);

    try {
        query.execute();
    } catch (Exception ltheXcp) {
        getLog().error("{}() - process failure, with exception(s) : ", this.getClass().getSimpleName(), ltheXcp);
        ltheXcp.printStackTrace();
        throw ltheXcp;
    }

    Integer commentCount = (Integer) query.getOutputParameterValue(2);
    return commentCount.intValue();

}
 

Кто-нибудь знает, как выполнить такой вызов с помощью драйвера Sybase и @Query?

Комментарии:

1. можете ли вы создавать запросы непосредственно в Sybase? Вы пробовали, что там работает? У меня всегда были ошибки с sybase, потому что он ожидал имя владельца, например dbo.rp_surrogate()

2. Какой диалект был настроен в приложении?

3. Да, мы можем использовать репозиторий и объекты JPA для извлечения записей из таблиц и тому подобное. Диалект — org.hibernate.dialect.SybaseDialect .

4. Вы пробовали @Procedure , как описано здесь , если это имеет какое-либо значение?

Ответ №1:

Собственный запрос Sybase не будет поддерживать «Call» и использовать «exec».

 @Query(value = "exec rp_surrogate  ?1, ?2 ", nativeQuery = true)
int getSurrogateByQueryV1(String surrtype, Integer newsurr );